blob: 12ff110318e5039f1a58d7d238050184c160d9e7 [file] [log] [blame]
/*
* Copyright (C) 2007-2008 Esmertec AG.
* Copyright (C) 2007-2008 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.
*/
package com.android.im.app;
import com.android.im.IChatSession;
import com.android.im.IChatSessionManager;
import com.android.im.IContactListListener;
import com.android.im.IContactListManager;
import com.android.im.IImConnection;
import com.android.im.ISubscriptionListener;
import com.android.im.R;
import com.android.im.app.adapter.ContactListListenerAdapter;
import com.android.im.engine.Contact;
import com.android.im.engine.ContactListManager;
import com.android.im.engine.ImErrorInfo;
import com.android.im.provider.Imps;
import com.android.im.service.ImServiceConstants;
import android.app.Activity;
import android.app.AlertDialog;
import android.content.ContentUris;
import android.content.Context;
import android.content.DialogInterface;
import android.content.Intent;
import android.content.res.Resources;
import android.database.Cursor;
import android.graphics.Canvas;
import android.net.Uri;
import android.os.Parcel;
import android.os.Parcelable;
import android.os.RemoteException;
import android.util.AttributeSet;
import android.util.Log;
import android.view.View;
import android.widget.ExpandableListView;
import android.widget.LinearLayout;
import android.widget.ExpandableListView.OnChildClickListener;
public class ContactListView extends LinearLayout {
Activity mScreen;
IImConnection mConn;
SimpleAlertHandler mHandler;
private final IContactListListener mContactListListener;
UserPresenceView mPresenceView;
ExpandableListView mContactsList;
private ContactListTreeAdapter mAdapter;
private boolean mHideOfflineContacts;
private SavedState mSavedState;
private boolean mAutoRefresh = true;
public ContactListView(Context screen, AttributeSet attrs) {
super(screen, attrs);
mScreen = (Activity)screen;
mHandler = new SimpleAlertHandler(mScreen);
mContactListListener = new MyContactListListener(mHandler);
}
private class MyContactListListener extends ContactListListenerAdapter {
public MyContactListListener(SimpleAlertHandler handler) {
super(handler);
}
@Override
public void onAllContactListsLoaded() {
if (mAdapter != null) {
mAdapter.startAutoRequery();
}
}
}
private final ISubscriptionListener.Stub mSubscriptionListener = new ISubscriptionListener.Stub() {
public void onSubScriptionRequest(Contact from) {
querySubscription();
}
public void onSubscriptionApproved(String contact) {
querySubscription();
}
public void onSubscriptionDeclined(String contact) {
querySubscription();
}
private void querySubscription() {
if (mAdapter != null) {
mAdapter.startQuerySubscriptions();
}
}
};
@Override
protected void onFinishInflate() {
super.onFinishInflate();
mPresenceView = (UserPresenceView)findViewById(R.id.userPresence);
mContactsList = (ExpandableListView) findViewById(R.id.contactsList);
mContactsList.setOnChildClickListener(mOnChildClickListener);
}
public ExpandableListView getListView() {
return mContactsList;
}
public void setConnection(IImConnection conn) {
if (mConn != conn) {
if (mConn != null) {
unregisterListeners();
}
mConn = conn;
if (conn != null) {
registerListeners();
mPresenceView.setConnection(conn);
if (mAdapter == null) {
mAdapter = new ContactListTreeAdapter(conn, mScreen);
mAdapter.setHideOfflineContacts(mHideOfflineContacts);
mContactsList.setAdapter(mAdapter);
mContactsList.setOnScrollListener(mAdapter);
if (mSavedState != null) {
int[] expandedGroups = mSavedState.mExpandedGroups;
if(expandedGroups != null) {
for (int group : expandedGroups) {
mContactsList.expandGroup(group);
}
}
}
} else {
mAdapter.changeConnection(conn);
}
try {
IContactListManager listMgr = conn.getContactListManager();
if (listMgr.getState() == ContactListManager.LISTS_LOADED) {
mAdapter.startAutoRequery();
}
} catch (RemoteException e) {
Log.e(ImApp.LOG_TAG, "Service died!");
}
}
} else {
mContactsList.invalidateViews();
}
}
public void setHideOfflineContacts(boolean hide) {
if (mAdapter != null) {
mAdapter.setHideOfflineContacts(hide);
} else {
mHideOfflineContacts = hide;
}
}
public void startChat() {
startChat(getSelectedContact());
}
public void startChatAtPosition(long packedPosition) {
startChat(getContactAtPosition(packedPosition));
}
void startChat(Cursor c) {
if (c != null) {
long id = c.getLong(c.getColumnIndexOrThrow(Imps.Contacts._ID));
String username = c.getString(c.getColumnIndexOrThrow(Imps.Contacts.USERNAME));
try {
IChatSessionManager manager = mConn.getChatSessionManager();
IChatSession session = manager.getChatSession(username);
if(session == null) {
manager.createChatSession(username);
}
Uri data = ContentUris.withAppendedId(Imps.Chats.CONTENT_URI, id);
Intent i = new Intent(Intent.ACTION_VIEW, data);
i.addCategory(ImApp.IMPS_CATEGORY);
mScreen.startActivity(i);
setAutoRefreshContacts(false);
} catch (RemoteException e) {
mHandler.showServiceErrorAlert();
}
clearFocusIfEmpty(c);
}
}
private void clearFocusIfEmpty(Cursor c) {
// clear focus if there's only one item so that it would focus on the
// "empty" item after the contact removed.
if (c.getCount() == 1) {
clearFocus();
}
}
public void endChat() {
endChat(getSelectedContact());
}
public void endChatAtPosition(long packedPosition) {
endChat(getContactAtPosition(packedPosition));
}
void endChat(Cursor c) {
if(c != null) {
String username = c.getString(c.getColumnIndexOrThrow(Imps.Contacts.USERNAME));
try {
IChatSessionManager manager = mConn.getChatSessionManager();
IChatSession session = manager.getChatSession(username);
if(session != null) {
session.leave();
}
} catch (RemoteException e) {
mHandler.showServiceErrorAlert();
}
clearFocusIfEmpty(c);
}
}
public void viewContactPresence() {
viewContactPresence(getSelectedContact());
}
public void viewContactPresenceAtPostion(long packedPosition) {
viewContactPresence(getContactAtPosition(packedPosition));
}
public void viewContactPresence(Cursor c) {
if (c != null) {
long id = c.getLong(c.getColumnIndexOrThrow(Imps.Contacts._ID));
Uri data = ContentUris.withAppendedId(Imps.Contacts.CONTENT_URI, id);
Intent i = new Intent(Intent.ACTION_VIEW, data);
mScreen.startActivity(i);
}
}
public boolean isContactAtPosition(long packedPosition) {
int type = ExpandableListView.getPackedPositionType(packedPosition);
int groupPosition = ExpandableListView.getPackedPositionGroup(packedPosition);
return (type == ExpandableListView.PACKED_POSITION_TYPE_CHILD)
&& !mAdapter.isPosForSubscription(groupPosition);
}
public boolean isContactSelected() {
long pos = mContactsList.getSelectedPosition();
return isContactAtPosition(pos);
}
public boolean isConversationAtPosition(long packedPosition) {
int type = ExpandableListView.getPackedPositionType(packedPosition);
int groupPosition = ExpandableListView.getPackedPositionGroup(packedPosition);
return (type == ExpandableListView.PACKED_POSITION_TYPE_CHILD)
&& mAdapter.isPosForOngoingConversation(groupPosition);
}
public boolean isConversationSelected () {
long pos = mContactsList.getSelectedPosition();
return isConversationAtPosition(pos);
}
public boolean isContactsLoaded() {
try {
IContactListManager manager = mConn.getContactListManager();
return (manager.getState() == ContactListManager.LISTS_LOADED);
} catch (RemoteException e) {
mHandler.showServiceErrorAlert();
return false;
}
}
public void removeContact() {
removeContact(getSelectedContact());
}
public void removeContactAtPosition(long packedPosition) {
removeContact(getContactAtPosition(packedPosition));
}
void removeContact(Cursor c) {
if (c == null) {
mHandler.showAlert(R.string.error, R.string.select_contact);
} else {
String nickname = c.getString(c.getColumnIndexOrThrow(Imps.Contacts.NICKNAME));
final String address = c.getString(c.getColumnIndexOrThrow(Imps.Contacts.USERNAME));
DialogInterface.OnClickListener confirmListener = new DialogInterface.OnClickListener(){
public void onClick(DialogInterface dialog, int whichButton) {
try {
IContactListManager manager = mConn.getContactListManager();
int res = manager.removeContact(address);
if (res != ImErrorInfo.NO_ERROR) {
mHandler.showAlert(R.string.error,
ErrorResUtils.getErrorRes(getResources(), res, address));
}
} catch (RemoteException e) {
mHandler.showServiceErrorAlert();
}
}
};
Resources r = getResources();
new AlertDialog.Builder(mContext)
.setTitle(R.string.confirm)
.setMessage(r.getString(R.string.confirm_delete_contact, nickname))
.setPositiveButton(R.string.yes, confirmListener) // default button
.setNegativeButton(R.string.no, null)
.setCancelable(false)
.show();
clearFocusIfEmpty(c);
}
}
public void blockContact() {
blockContact(getSelectedContact());
}
public void blockContactAtPosition(long packedPosition) {
blockContact(getContactAtPosition(packedPosition));
}
void blockContact(Cursor c) {
if (c == null) {
mHandler.showAlert(R.string.error, R.string.select_contact);
} else {
String nickname = c.getString(c.getColumnIndexOrThrow(Imps.Contacts.NICKNAME));
final String address = c.getString(c.getColumnIndexOrThrow(Imps.Contacts.USERNAME));
DialogInterface.OnClickListener confirmListener = new DialogInterface.OnClickListener(){
public void onClick(DialogInterface dialog, int whichButton) {
try {
IContactListManager manager = mConn.getContactListManager();
int res = manager.blockContact(address);
if (res != ImErrorInfo.NO_ERROR) {
mHandler.showAlert(R.string.error,
ErrorResUtils.getErrorRes(getResources(), res, address));
}
} catch (RemoteException e) {
mHandler.showServiceErrorAlert();
}
}
};
Resources r = getResources();
new AlertDialog.Builder(mContext)
.setTitle(R.string.confirm)
.setMessage(r.getString(R.string.confirm_block_contact, nickname))
.setPositiveButton(R.string.yes, confirmListener) // default button
.setNegativeButton(R.string.no, null)
.setCancelable(false)
.show();
clearFocusIfEmpty(c);
}
}
public Cursor getContactAtPosition(long packedPosition) {
int type = ExpandableListView.getPackedPositionType(packedPosition);
if (type == ExpandableListView.PACKED_POSITION_TYPE_CHILD) {
int groupPosition = ExpandableListView.getPackedPositionGroup(packedPosition);
int childPosition = ExpandableListView.getPackedPositionChild(packedPosition);
return (Cursor) mAdapter.getChild(groupPosition, childPosition);
}
return null;
}
public Cursor getSelectedContact() {
long pos = mContactsList.getSelectedPosition();
if (ExpandableListView.getPackedPositionType(pos)
== ExpandableListView.PACKED_POSITION_TYPE_CHILD) {
return (Cursor)mContactsList.getSelectedItem();
}
return null;
}
public String getSelectedContactList() {
long pos = mContactsList.getSelectedPosition();
int groupPos = ExpandableListView.getPackedPositionGroup(pos);
if (groupPos == -1) {
return null;
}
Cursor cursor = (Cursor)mAdapter.getGroup(groupPos);
if (cursor == null) {
return null;
}
return cursor.getString(cursor.getColumnIndexOrThrow(Imps.ContactList.NAME));
}
private void registerListeners() {
try{
IContactListManager listManager = mConn.getContactListManager();
listManager.registerContactListListener(mContactListListener);
listManager.registerSubscriptionListener(mSubscriptionListener);
}catch(RemoteException e) {
mHandler.showServiceErrorAlert();
}
}
private void unregisterListeners() {
try{
IContactListManager listManager = mConn.getContactListManager();
listManager.unregisterContactListListener(mContactListListener);
listManager.unregisterSubscriptionListener(mSubscriptionListener);
}catch(RemoteException e) {
mHandler.showServiceErrorAlert();
}
}
private final OnChildClickListener mOnChildClickListener = new OnChildClickListener() {
public boolean onChildClick(ExpandableListView parent, View v, int groupPosition,
int childPosition, long id) {
Cursor cursor = (Cursor)parent.getExpandableListAdapter().getChild(
groupPosition, childPosition);
if (cursor == null) {
Log.w(ImApp.LOG_TAG,
"[ContactListView.OnChildClickListener.onChildClick] cursor null! groupPos="
+ groupPosition + ", childPos=" + childPosition,
new RuntimeException());
return false;
}
int subscriptionType = cursor.getInt(ContactView.COLUMN_SUBSCRIPTION_TYPE);
int subscriptionStatus = cursor.getInt(ContactView.COLUMN_SUBSCRIPTION_STATUS);
if ((subscriptionType == Imps.Contacts.SUBSCRIPTION_TYPE_FROM)
&& (subscriptionStatus == Imps.Contacts.SUBSCRIPTION_STATUS_SUBSCRIBE_PENDING)){
long providerId = cursor.getLong(ContactView.COLUMN_CONTACT_PROVIDER);
String username = cursor.getString(ContactView.COLUMN_CONTACT_USERNAME);
Intent intent = new Intent(ImServiceConstants.ACTION_MANAGE_SUBSCRIPTION,
ContentUris.withAppendedId(Imps.Contacts.CONTENT_URI, id));
intent.putExtra(ImServiceConstants.EXTRA_INTENT_PROVIDER_ID, providerId);
intent.putExtra(ImServiceConstants.EXTRA_INTENT_FROM_ADDRESS, username);
mScreen.startActivity(intent);
} else {
startChat(cursor);
}
return true;
}
};
static class SavedState extends BaseSavedState {
int[] mExpandedGroups;
SavedState(Parcelable superState, int[] expandedGroups) {
super(superState);
mExpandedGroups = expandedGroups;
}
private SavedState(Parcel in) {
super(in);
mExpandedGroups = in.createIntArray();
}
@Override
public void writeToParcel(Parcel out, int flags) {
super.writeToParcel(out, flags);
out.writeIntArray(mExpandedGroups);
}
public static final Parcelable.Creator<SavedState> CREATOR
= new Parcelable.Creator<SavedState>() {
public SavedState createFromParcel(Parcel in) {
return new SavedState(in);
}
public SavedState[] newArray(int size) {
return new SavedState[size];
}
};
}
@Override
public Parcelable onSaveInstanceState() {
Parcelable superState = super.onSaveInstanceState();
int[] expandedGroups = mAdapter == null ? null
: mAdapter.getExpandedGroups();
return new SavedState(superState, expandedGroups);
}
@Override
public void onRestoreInstanceState(Parcelable state) {
SavedState ss = (SavedState) state;
super.onRestoreInstanceState(ss.getSuperState());
mSavedState = ss;
}
protected void setAutoRefreshContacts(boolean isRefresh) {
mAutoRefresh = isRefresh;
}
@Override
protected void onLayout(boolean changed, int l, int t, int r, int b) {
if (mAutoRefresh) {
super.onLayout(changed, l, t, r, b);
}
}
}