summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--res/drawable-hdpi/ic_call_log_blue.pngbin0 -> 1734 bytes
-rw-r--r--res/drawable-mdpi/ic_call_log_blue.pngbin0 -> 1141 bytes
-rw-r--r--res/drawable-xhdpi/ic_call_log_blue.pngbin0 -> 2386 bytes
-rw-r--r--res/drawable-xxhdpi/ic_call_log_blue.pngbin0 -> 2967 bytes
-rw-r--r--res/layout/call_log_list_item.xml6
-rw-r--r--res/layout/call_log_list_item_extra.xml50
-rw-r--r--src/com/android/dialer/calllog/CallLogAdapter.java127
-rw-r--r--src/com/android/dialer/list/PhoneFavoriteFragment.java24
-rw-r--r--src/com/android/dialerbind/ObjectFactory.java3
-rw-r--r--tests/src/com/android/dialer/calllog/CallLogAdapterTest.java2
10 files changed, 206 insertions, 6 deletions
diff --git a/res/drawable-hdpi/ic_call_log_blue.png b/res/drawable-hdpi/ic_call_log_blue.png
new file mode 100644
index 000000000..92af15f7b
--- /dev/null
+++ b/res/drawable-hdpi/ic_call_log_blue.png
Binary files differ
diff --git a/res/drawable-mdpi/ic_call_log_blue.png b/res/drawable-mdpi/ic_call_log_blue.png
new file mode 100644
index 000000000..b9209adca
--- /dev/null
+++ b/res/drawable-mdpi/ic_call_log_blue.png
Binary files differ
diff --git a/res/drawable-xhdpi/ic_call_log_blue.png b/res/drawable-xhdpi/ic_call_log_blue.png
new file mode 100644
index 000000000..9d92573b0
--- /dev/null
+++ b/res/drawable-xhdpi/ic_call_log_blue.png
Binary files differ
diff --git a/res/drawable-xxhdpi/ic_call_log_blue.png b/res/drawable-xxhdpi/ic_call_log_blue.png
new file mode 100644
index 000000000..0a55a7572
--- /dev/null
+++ b/res/drawable-xxhdpi/ic_call_log_blue.png
Binary files differ
diff --git a/res/layout/call_log_list_item.xml b/res/layout/call_log_list_item.xml
index c49b4b008..1bd448c5a 100644
--- a/res/layout/call_log_list_item.xml
+++ b/res/layout/call_log_list_item.xml
@@ -140,4 +140,10 @@
android:paddingTop="@dimen/call_log_inner_margin"
android:paddingBottom="@dimen/call_log_inner_margin" />
+ <!-- Displays the extra link section -->
+ <ViewStub android:id="@+id/link_stub"
+ android:layout="@layout/call_log_list_item_extra"
+ android:layout_width="match_parent"
+ android:layout_height="wrap_content"/>
+
</view>
diff --git a/res/layout/call_log_list_item_extra.xml b/res/layout/call_log_list_item_extra.xml
new file mode 100644
index 000000000..672abf12f
--- /dev/null
+++ b/res/layout/call_log_list_item_extra.xml
@@ -0,0 +1,50 @@
+<?xml version="1.0" encoding="utf-8"?>
+
+<!--
+ ~ Copyright (C) 2013 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
+ -->
+
+<!-- Can't use merge here because this is referenced via a ViewStub -->
+<FrameLayout xmlns:android="http://schemas.android.com/apk/res/android"
+ android:layout_width="match_parent"
+ android:layout_height="wrap_content"
+ android:id="@+id/badge_container">
+
+ <View android:layout_width="match_parent"
+ android:layout_height="1px"
+ android:layout_marginStart="@dimen/call_log_outer_margin"
+ android:layout_marginEnd="@dimen/call_log_outer_margin"
+ android:background="@color/favorite_contacts_separator_color"/>
+
+ <LinearLayout android:id="@+id/badge_link_container"
+ android:layout_width="match_parent"
+ android:layout_height="wrap_content"
+ android:paddingStart="@dimen/call_log_outer_margin"
+ android:paddingEnd="@dimen/call_log_outer_margin"
+ android:paddingTop="4dip"
+ android:paddingBottom="4dip"
+ android:background="?android:attr/selectableItemBackground"
+ android:clickable="true">
+ <ImageView android:layout_width="wrap_content"
+ android:layout_height="wrap_content"
+ android:id="@+id/badge_image"
+ android:padding="@dimen/call_log_outer_margin"/>
+ <TextView android:layout_width="wrap_content"
+ android:layout_height="wrap_content"
+ android:id="@+id/badge_text"
+ android:textColor="@color/dialpad_primary_text_color"
+ android:layout_gravity="center_vertical"/>
+ </LinearLayout>
+</FrameLayout> \ No newline at end of file
diff --git a/src/com/android/dialer/calllog/CallLogAdapter.java b/src/com/android/dialer/calllog/CallLogAdapter.java
index 37dbdf3cf..b2493cf97 100644
--- a/src/com/android/dialer/calllog/CallLogAdapter.java
+++ b/src/com/android/dialer/calllog/CallLogAdapter.java
@@ -18,6 +18,7 @@ package com.android.dialer.calllog;
import android.content.ContentValues;
import android.content.Context;
+import android.content.Intent;
import android.content.res.Resources;
import android.database.Cursor;
import android.net.Uri;
@@ -29,7 +30,10 @@ import android.text.TextUtils;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
+import android.view.ViewStub;
import android.view.ViewTreeObserver;
+import android.widget.ImageView;
+import android.widget.TextView;
import com.android.common.widget.GroupingListAdapter;
import com.android.contacts.common.ContactPhotoManager;
@@ -48,6 +52,7 @@ import java.util.LinkedList;
*/
public class CallLogAdapter extends GroupingListAdapter
implements ViewTreeObserver.OnPreDrawListener, CallLogGroupBuilder.GroupCreator {
+
/** Interface used to initiate a refresh of the content. */
public interface CallFetcher {
public void fetchCalls();
@@ -182,6 +187,15 @@ public class CallLogAdapter extends GroupingListAdapter
* action should be set to call a number instead of opening the detail page. */
private boolean mUseCallAsPrimaryAction = false;
+ private boolean mIsCallLog = true;
+ private int mNumMissedCalls = 0;
+ private int mNumMissedCallsShown = 0;
+ private Uri mCurrentPhotoUri;
+
+ private View mBadgeContainer;
+ private ImageView mBadgeImageView;
+ private TextView mBadgeText;
+
/** Listener for the primary action in the list, opens the call details. */
private final View.OnClickListener mPrimaryActionListener = new View.OnClickListener() {
@Override
@@ -232,13 +246,15 @@ public class CallLogAdapter extends GroupingListAdapter
};
public CallLogAdapter(Context context, CallFetcher callFetcher,
- ContactInfoHelper contactInfoHelper, boolean useCallAsPrimaryAction) {
+ ContactInfoHelper contactInfoHelper, boolean useCallAsPrimaryAction,
+ boolean isCallLog) {
super(context);
mContext = context;
mCallFetcher = callFetcher;
mContactInfoHelper = contactInfoHelper;
mUseCallAsPrimaryAction = useCallAsPrimaryAction;
+ mIsCallLog = isCallLog;
mContactInfoCache = ExpirableCache.create(CONTACT_INFO_CACHE_SIZE);
mRequests = new LinkedList<ContactInfoRequest>();
@@ -614,12 +630,107 @@ public class CallLogAdapter extends GroupingListAdapter
mViewTreeObserver.addOnPreDrawListener(this);
}
- postBindView(views, info, details);
+ bindBadge(view, info, details, callType);
+ }
+
+ protected void bindBadge(View view, ContactInfo info, PhoneCallDetails details, int callType) {
+
+ // Do not show badge in call log.
+ if (!mIsCallLog) {
+ final int numMissed = getNumMissedCalls(callType);
+ final ViewStub stub = (ViewStub) view.findViewById(R.id.link_stub);
+ if (shouldShowBadge(numMissed, info, details)) {
+
+ // stub will be null if it was already inflated.
+ if (stub != null) {
+ final View inflated = stub.inflate();
+ inflated.setVisibility(View.VISIBLE);
+ mBadgeContainer = inflated.findViewById(R.id.badge_link_container);
+ mBadgeImageView = (ImageView) inflated.findViewById(R.id.badge_image);
+ mBadgeText = (TextView) inflated.findViewById(R.id.badge_text);
+ }
+
+ mBadgeContainer.setOnClickListener(getBadgeClickListener());
+ mBadgeImageView.setImageResource(getBadgeImageResId());
+ mBadgeText.setText(getBadgeText(numMissed));
+
+ mNumMissedCallsShown = numMissed;
+ } else {
+ // Hide badge if it was previously shown.
+ if (stub == null) {
+ final View container = view.findViewById(R.id.badge_container);
+ if (container != null) {
+ container.setVisibility(View.GONE);
+ }
+ }
+ }
+ }
+ }
+
+ public void setMissedCalls(Cursor data) {
+ final int missed;
+ if (data == null) {
+ missed = 0;
+ } else {
+ missed = data.getCount();
+ }
+ // Only need to update if the number of calls changed.
+ if (missed != mNumMissedCalls) {
+ mNumMissedCalls = missed;
+ notifyDataSetChanged();
+ }
+ }
+
+ protected View.OnClickListener getBadgeClickListener() {
+ return new View.OnClickListener() {
+ @Override
+ public void onClick(View v) {
+ final Intent intent = new Intent(mContext, CallLogActivity.class);
+ mContext.startActivity(intent);
+ }
+ };
+ }
+
+ /**
+ * Get the resource id for the image to be shown for the badge.
+ */
+ protected int getBadgeImageResId() {
+ return R.drawable.ic_call_log_blue;
+ }
+
+ /**
+ * Get the text to be shown for the badge.
+ *
+ * @param numMissed The number of missed calls.
+ */
+ protected String getBadgeText(int numMissed) {
+ return mContext.getResources().getString(R.string.num_missed_calls, numMissed);
}
- protected void postBindView(CallLogListItemViews views, ContactInfo info,
+ /**
+ * Whether to show the badge.
+ *
+ * @param numMissedCalls The number of missed calls.
+ * @param info The contact info.
+ * @param details The call detail.
+ * @return {@literal true} if badge should be shown. {@literal false} otherwise.
+ */
+ protected boolean shouldShowBadge(int numMissedCalls, ContactInfo info,
PhoneCallDetails details) {
- // no-op
+ // Do not process if the data has not changed (optimization since bind view is called
+ // multiple times due to contact lookup).
+ if (numMissedCalls == mNumMissedCallsShown) {
+ return false;
+ }
+ return numMissedCalls > 0;
+ }
+
+ private int getNumMissedCalls(int callType) {
+ if (callType == Calls.MISSED_TYPE) {
+ // Exclude the current missed call shown in the shortcut.
+ return mNumMissedCalls - 1;
+ }
+ return mNumMissedCalls;
}
/** Checks whether the contact info from the call log matches the one from the contacts db. */
@@ -733,11 +844,19 @@ public class CallLogAdapter extends GroupingListAdapter
}
private void setPhoto(CallLogListItemViews views, long photoId, Uri contactUri) {
+ mCurrentPhotoUri = null;
views.quickContactView.assignContactUri(contactUri);
mContactPhotoManager.loadThumbnail(views.quickContactView, photoId, false /* darkTheme */);
}
private void setPhoto(CallLogListItemViews views, Uri photoUri, Uri contactUri) {
+ if (photoUri.equals(mCurrentPhotoUri)) {
+ // photo manager will perform a fade in transition. To avoid flicker, do not set the
+ // same photo multiple times.
+ return;
+ }
+
+ mCurrentPhotoUri = photoUri;
views.quickContactView.assignContactUri(contactUri);
mContactPhotoManager.loadDirectoryPhoto(views.quickContactView, photoUri,
false /* darkTheme */);
diff --git a/src/com/android/dialer/list/PhoneFavoriteFragment.java b/src/com/android/dialer/list/PhoneFavoriteFragment.java
index d731786a5..32ec71c26 100644
--- a/src/com/android/dialer/list/PhoneFavoriteFragment.java
+++ b/src/com/android/dialer/list/PhoneFavoriteFragment.java
@@ -30,6 +30,7 @@ import android.database.MatrixCursor;
import android.graphics.Rect;
import android.net.Uri;
import android.os.Bundle;
+import android.provider.CallLog;
import android.util.Log;
import android.view.LayoutInflater;
import android.view.View;
@@ -81,6 +82,7 @@ public class PhoneFavoriteFragment extends Fragment implements OnItemClickListen
* Used with LoaderManager.
*/
private static int LOADER_ID_CONTACT_TILE = 1;
+ private static int MISSED_CALL_LOADER = 2;
private static final String KEY_LAST_DISMISSED_CALL_SHORTCUT_DATE =
"key_last_dismissed_call_shortcut_date";
@@ -94,6 +96,27 @@ public class PhoneFavoriteFragment extends Fragment implements OnItemClickListen
public void onCallNumberDirectly(String phoneNumber);
}
+ private class MissedCallLogLoaderListener implements LoaderManager.LoaderCallbacks<Cursor> {
+
+ @Override
+ public Loader<Cursor> onCreateLoader(int id, Bundle args) {
+ final Uri uri = CallLog.Calls.CONTENT_URI;
+ final String[] projection = new String[] {CallLog.Calls.TYPE};
+ final String selection = CallLog.Calls.TYPE + " = " + CallLog.Calls.MISSED_TYPE +
+ " AND " + CallLog.Calls.IS_READ + " = 0";
+ return new CursorLoader(getActivity(), uri, projection, selection, null, null);
+ }
+
+ @Override
+ public void onLoadFinished(Loader<Cursor> cursorLoader, Cursor data) {
+ mCallLogAdapter.setMissedCalls(data);
+ }
+
+ @Override
+ public void onLoaderReset(Loader<Cursor> cursorLoader) {
+ }
+ }
+
private class ContactTileLoaderListener implements LoaderManager.LoaderCallbacks<Cursor> {
@Override
public CursorLoader onCreateLoader(int id, Bundle args) {
@@ -299,6 +322,7 @@ public class PhoneFavoriteFragment extends Fragment implements OnItemClickListen
// 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.
getLoaderManager().initLoader(LOADER_ID_CONTACT_TILE, null, mContactTileLoaderListener);
+ getLoaderManager().initLoader(MISSED_CALL_LOADER, null, new MissedCallLogLoaderListener());
}
/**
diff --git a/src/com/android/dialerbind/ObjectFactory.java b/src/com/android/dialerbind/ObjectFactory.java
index 6286c05ba..c43dffcea 100644
--- a/src/com/android/dialerbind/ObjectFactory.java
+++ b/src/com/android/dialerbind/ObjectFactory.java
@@ -37,6 +37,7 @@ public class ObjectFactory {
public static CallLogAdapter newCallLogAdapter(Context context, CallFetcher callFetcher,
ContactInfoHelper contactInfoHelper, boolean useCallAsPrimaryAction,
boolean isCallLog) {
- return new CallLogAdapter(context, callFetcher, contactInfoHelper, useCallAsPrimaryAction);
+ return new CallLogAdapter(context, callFetcher, contactInfoHelper, useCallAsPrimaryAction,
+ isCallLog);
}
}
diff --git a/tests/src/com/android/dialer/calllog/CallLogAdapterTest.java b/tests/src/com/android/dialer/calllog/CallLogAdapterTest.java
index 55e422498..12cdb2b99 100644
--- a/tests/src/com/android/dialer/calllog/CallLogAdapterTest.java
+++ b/tests/src/com/android/dialer/calllog/CallLogAdapterTest.java
@@ -212,7 +212,7 @@ public class CallLogAdapterTest extends AndroidTestCase {
public TestCallLogAdapter(Context context, CallFetcher callFetcher,
ContactInfoHelper contactInfoHelper) {
- super(context, callFetcher, contactInfoHelper, false);
+ super(context, callFetcher, contactInfoHelper, false, false);
}
@Override