/*
* 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 info.guardianproject.otr.app.im.app;
import info.guardianproject.otr.app.im.IChatSession;
import info.guardianproject.otr.app.im.IChatSessionManager;
import info.guardianproject.otr.app.im.IImConnection;
import info.guardianproject.otr.app.im.R;
import info.guardianproject.otr.app.im.app.ContactListFilterView.ContactListListener;
import info.guardianproject.otr.app.im.app.adapter.ConnectionListenerAdapter;
import info.guardianproject.otr.app.im.engine.ImConnection;
import info.guardianproject.otr.app.im.engine.ImErrorInfo;
import info.guardianproject.otr.app.im.provider.Imps;
import java.util.Observable;
import java.util.Observer;
import android.app.Activity;
import android.app.AlertDialog;
import android.content.ContentResolver;
import android.content.ContentUris;
import android.content.Context;
import android.content.DialogInterface;
import android.content.Intent;
import android.database.Cursor;
import android.net.Uri;
import android.os.Bundle;
import android.os.Handler;
import android.os.Message;
import android.os.RemoteException;
import android.util.AttributeSet;
import android.util.Log;
import android.view.ContextMenu;
import android.view.ContextMenu.ContextMenuInfo;
import android.view.KeyEvent;
import android.view.LayoutInflater;
import android.view.View;
import android.view.View.OnClickListener;
import android.view.ViewGroup;
import android.widget.AdapterView;
import android.widget.AdapterView.AdapterContextMenuInfo;
import android.widget.AdapterView.OnItemSelectedListener;
import android.widget.CursorAdapter;
import android.widget.ExpandableListView.ExpandableListContextMenuInfo;
import android.widget.ListView;
import android.widget.Spinner;
import android.widget.TextView;
import com.actionbarsherlock.view.Menu;
import com.actionbarsherlock.view.MenuInflater;
import com.actionbarsherlock.view.MenuItem;
import com.jeremyfeinstein.slidingmenu.lib.SlidingMenu;
// mScreen.finish();
//mContactListView.setAutoRefreshContacts(false);
public class ChatListOldActivity extends ThemeableActivity implements View.OnCreateContextMenuListener, ContactListListener {
private static final int MENU_START_CONVERSATION = Menu.FIRST;
private static final int MENU_VIEW_PROFILE = Menu.FIRST + 1;
private static final int MENU_BLOCK_CONTACT = Menu.FIRST + 2;
private static final int MENU_DELETE_CONTACT = Menu.FIRST + 3;
private static final int MENU_END_CONVERSATION = Menu.FIRST + 4;
private static final String FILTER_STATE_KEY = "Filtering";
ImApp mApp;
// long mProviderId;
// long mAccountId;
// IImConnection mConn;
ActiveChatListView mActiveChatListView;
ContactListFilterView mFilterView;
SlidingMenu menu;
ContextMenuHandler mContextMenuHandler;
boolean mIsFiltering;
UserPresenceView mPresenceView;
Imps.ProviderSettings.QueryMap mGlobalSettingMap;
boolean mDestroyed;
private ConnectionListenerAdapter mConnectionListener;
long[] mAccountIds;
private long mLastProviderId = -1;
Handler mHandler = new Handler() {
@Override
public void handleMessage(Message msg) {
/*
long providerId = ((long) msg.arg1 << 32) | msg.arg2;
if (providerId != mProviderId) {
return;
}
*/
switch (msg.what) {
case ImApp.EVENT_CONNECTION_LOGGED_IN:
log("Connection resumed");
//updateWarningView();
return;
case ImApp.EVENT_CONNECTION_SUSPENDED:
log("Connection suspended");
// updateWarningView();
return;
case ImApp.EVENT_CONNECTION_DISCONNECTED:
log("Handle event connection disconnected.");
// updateWarningView();
// promptDisconnectedEvent(msg);
return;
}
super.handleMessage(msg);
}
};
@Override
protected void onCreate(Bundle icicle) {
super.onCreate(icicle);
LayoutInflater inflate = getLayoutInflater();
mActiveChatListView = (ActiveChatListView) inflate.inflate(R.layout.chat_list_view, null);
setContentView(mActiveChatListView);
getSherlock().getActionBar().setHomeButtonEnabled(true);
getSherlock().getActionBar().setDisplayHomeAsUpEnabled(true);
mApp = (ImApp)getApplication();
mGlobalSettingMap = new Imps.ProviderSettings.QueryMap(getContentResolver(), true, mHandler);
mContextMenuHandler = new ContextMenuHandler();
mActiveChatListView.getListView().setOnCreateContextMenuListener(this);
// setupSideBar();
}
/*
private void setupSideBar ()
{
menu = new SlidingMenu(this);
menu.setMode(SlidingMenu.LEFT);
menu.setTouchModeAbove(SlidingMenu.TOUCHMODE_FULLSCREEN);
menu.setShadowWidthRes(R.dimen.shadow_width);
menu.setShadowDrawable(R.drawable.shadow);
menu.setBehindOffsetRes(R.dimen.slidingmenu_offset);
menu.setFadeDegree(0.35f);
menu.attachToActivity(this, SlidingMenu.SLIDING_CONTENT);
mFilterView = (ContactListFilterView) getLayoutInflater().inflate(
R.layout.contact_list_filter_view, null);
mFilterView.setListener(this);
mPresenceView = (UserPresenceView) mFilterView.findViewById(R.id.userPresence);
mConnectionListener = new ConnectionListenerAdapter(mHandler) {
@Override
public void onConnectionStateChange(IImConnection connection, int state,
ImErrorInfo error) {
mPresenceView.loggingIn(state == ImConnection.LOGGING_IN);
}
};
mGlobalSettingMap.addObserver(new Observer() {
public void update(Observable observed, Object updateData) {
if (!mDestroyed) {
mConnectionListener = new ConnectionListenerAdapter(mHandler) {
@Override
public void onConnectionStateChange(IImConnection connection, int state,
ImErrorInfo error) {
mPresenceView.loggingIn(state == ImConnection.LOGGING_IN);
}
};
}
}
});
menu.setMenu(mFilterView);
setupActionBarList();
mApp.registerForConnEvents(mHandler);
}
*/
private void initAccount (long accountId)
{
ContentResolver cr = getContentResolver();
Cursor c = cr.query(ContentUris.withAppendedId(Imps.Account.CONTENT_URI, accountId), null,
null, null, null);
if (c == null) {
// finish();
return;
}
if (!c.moveToFirst()) {
c.close();
// finish();
return;
}
mLastProviderId = c.getLong(c.getColumnIndexOrThrow(Imps.Account.PROVIDER));
mHandler = new MyHandler(this);
initConnection (accountId, mLastProviderId);
c.close();
}
private void initConnection (long accountId, long providerId)
{
mApp.dismissNotifications(providerId);
IImConnection conn = mApp.getConnection(providerId);
if (conn == null)
{
try {
conn = mApp.createConnection(providerId, accountId);
} catch (RemoteException e) {
Log.e(ImApp.LOG_TAG,"error creating connection",e);
}
}
if (conn != null)
{
mActiveChatListView.setConnection(conn);
mPresenceView.setConnection(conn);
try {
mPresenceView.loggingIn(conn.getState() == ImConnection.LOGGING_IN);
} catch (RemoteException e) {
mPresenceView.loggingIn(false);
// mHandler.showServiceErrorAlert();
}
Uri uri = mGlobalSettingMap.getHideOfflineContacts() ? Imps.Contacts.CONTENT_URI_ONLINE_CONTACTS_BY
: Imps.Contacts.CONTENT_URI_CONTACTS_BY;
uri = ContentUris.withAppendedId(uri, providerId);
uri = ContentUris.withAppendedId(uri, accountId);
mFilterView.doFilter(uri, null);
}
}
private void setupActionBarList ()
{
Cursor providerCursor = managedQuery(Imps.Provider.CONTENT_URI_WITH_ACCOUNT, PROVIDER_PROJECTION,
Imps.Provider.CATEGORY + "=?" + " AND " + Imps.Provider.ACTIVE_ACCOUNT_USERNAME + " NOT NULL",
new String[] { ImApp.IMPS_CATEGORY } /* selection args */,
Imps.Provider.DEFAULT_SORT_ORDER);
// + " AND " + Imps.Provider.ACCOUNT_CONNECTION_STATUS + " != 0"
/* selection */
mAccountIds = new long[providerCursor.getCount()];
providerCursor.moveToFirst();
int activeAccountIdColumn = providerCursor.getColumnIndexOrThrow(Imps.Provider.ACTIVE_ACCOUNT_ID);
// int currentAccountIndex = -1;
for (int i = 0; i < mAccountIds.length; i++)
{
mAccountIds[i] = providerCursor.getLong(activeAccountIdColumn);
providerCursor.moveToNext();
}
providerCursor.moveToFirst();
ProviderAdapter pAdapter = new ProviderAdapter(this, providerCursor);
Spinner spinnerAccounts = (Spinner)mFilterView.findViewById(R.id.spinnerAccounts);
spinnerAccounts.setAdapter(pAdapter);
spinnerAccounts.setOnItemSelectedListener(new OnItemSelectedListener ()
{
@Override
public void onItemSelected(AdapterView<?> parent, View view, int itemPosition, long id) {
// mAccountId = mAccountIds[itemPosition];
//update account list
initAccount(mAccountIds[itemPosition]);
}
@Override
public void onNothingSelected(AdapterView<?> arg0) {
// TODO Auto-generated method stub
}
});
}
private class ProviderAdapter extends CursorAdapter {
private LayoutInflater mInflater;
@SuppressWarnings("deprecation")
public ProviderAdapter(Context context, Cursor c) {
super(context, c);
mInflater = LayoutInflater.from(context).cloneInContext(context);
mInflater.setFactory(new ProviderListItemFactory());
}
@Override
public View newView(Context context, Cursor cursor, ViewGroup parent) {
// create a custom view, so we can manage it ourselves. Mainly, we want to
// initialize the widget views (by calling getViewById()) in newView() instead of in
// bindView(), which can be called more often.
ProviderListItem view = (ProviderListItem) mInflater.inflate(R.layout.account_view_small,
parent, false);
view.init(cursor,false);
return view;
}
@Override
public void bindView(View view, Context context, Cursor cursor) {
((ProviderListItem) view).bindView(cursor);
}
}
private class ProviderListItemFactory implements LayoutInflater.Factory {
public View onCreateView(String name, Context context, AttributeSet attrs) {
if (name != null && name.equals(ProviderListItem.class.getName())) {
return new ProviderListItem(context, ChatListOldActivity.this, null);
}
return null;
}
}
private void signOut (long providerId)
{
IImConnection conn = ((ImApp)getApplication()).getConnection(providerId);
try {
if (conn != null)
conn.logout();
} catch (RemoteException e) {
Log.e("ChatList","error signing out",e);
}
}
private void showContactsList ()
{
// Intent intent = new Intent (this, ContactListActivity.class);
// intent.putExtra(ImServiceConstants.EXTRA_INTENT_ACCOUNT_ID, mAccountId);
// startActivity(intent);
if (menu != null)
menu.showMenu(true);
}
@Override
public boolean onCreateOptionsMenu(Menu menu) {
MenuInflater inflater = getSupportMenuInflater();
inflater.inflate(R.menu.chat_list_menu, menu);
return true;
}
@Override
public boolean onOptionsItemSelected(MenuItem item) {
switch (item.getItemId()) {
case R.id.menu_new_chat:
showContactsList ();
return true;
case R.id.menu_new_group_chat:
// showGroupChatDialog();
return true;
case R.id.menu_view_accounts:
startActivity(new Intent(getBaseContext(), ChooseAccountActivity.class));
// finish();
return true;
case R.id.menu_settings:
Intent intent = new Intent(this, SettingActivity.class);
startActivityForResult(intent,1);
return true;
// case R.id.menu_sign_out:
// signOut();
// return true;
}
return super.onOptionsItemSelected(item);
}
Intent getEditAccountIntent() {
Cursor mProviderCursor = managedQuery(Imps.Provider.CONTENT_URI_WITH_ACCOUNT,
PROVIDER_PROJECTION, Imps.Provider.CATEGORY + "=?" /* selection */,
new String[] { ImApp.IMPS_CATEGORY } /* selection args */,
Imps.Provider.DEFAULT_SORT_ORDER);
mProviderCursor.moveToFirst();
Intent intent = new Intent(Intent.ACTION_EDIT, ContentUris.withAppendedId(
Imps.Account.CONTENT_URI, mProviderCursor.getLong(ACTIVE_ACCOUNT_ID_COLUMN)));
intent.addCategory(mProviderCursor.getString(PROVIDER_CATEGORY_COLUMN));
intent.putExtra("isSignedIn", true);
return intent;
}
private static final String[] PROVIDER_PROJECTION = {
Imps.Provider._ID,
Imps.Provider.NAME,
Imps.Provider.FULLNAME,
Imps.Provider.CATEGORY,
Imps.Provider.ACTIVE_ACCOUNT_ID,
Imps.Provider.ACTIVE_ACCOUNT_USERNAME,
Imps.Provider.ACTIVE_ACCOUNT_PW,
Imps.Provider.ACTIVE_ACCOUNT_LOCKED,
Imps.Provider.ACTIVE_ACCOUNT_KEEP_SIGNED_IN,
Imps.Provider.ACCOUNT_PRESENCE_STATUS,
Imps.Provider.ACCOUNT_CONNECTION_STATUS, };
static final int PROVIDER_CATEGORY_COLUMN = 3;
static final int ACTIVE_ACCOUNT_ID_COLUMN = 4;
@Override
protected void onActivityResult(int requestCode, int resultCode, Intent data) {
//this is bad code for weird locale switching stuff
/**
if (requestCode == 1 && resultCode == 2)
{
Intent intent = getIntent();
finish();
startActivity(intent);
}*/
}
@Override
protected void onSaveInstanceState(Bundle outState) {
super.onSaveInstanceState(outState);
outState.putBoolean(FILTER_STATE_KEY, mIsFiltering);
}
@Override
protected void onRestoreInstanceState(Bundle savedInstanceState) {
boolean isFiltering = savedInstanceState.getBoolean(FILTER_STATE_KEY);
if (isFiltering) {
showFilterView();
}
super.onRestoreInstanceState(savedInstanceState);
}
@Override
public boolean dispatchKeyEvent(KeyEvent event) {
int keyCode = event.getKeyCode();
boolean handled = false;
if (mIsFiltering) {
handled = mFilterView.dispatchKeyEvent(event);
if (!handled && (KeyEvent.KEYCODE_BACK == keyCode)
&& (KeyEvent.ACTION_DOWN == event.getAction())) {
showChatListView();
handled = true;
}
} else {
handled = mActiveChatListView.dispatchKeyEvent(event);
if (!handled && isReadable(keyCode, event)
&& (KeyEvent.ACTION_DOWN == event.getAction())) {
showFilterView();
handled = mFilterView.dispatchKeyEvent(event);
}
}
if (!handled) {
handled = super.dispatchKeyEvent(event);
}
return handled;
}
private static boolean isReadable(int keyCode, KeyEvent event) {
if (KeyEvent.isModifierKey(keyCode) || event.isSystem()) {
return false;
}
switch (keyCode) {
case KeyEvent.KEYCODE_DPAD_CENTER:
case KeyEvent.KEYCODE_DPAD_DOWN:
case KeyEvent.KEYCODE_DPAD_LEFT:
case KeyEvent.KEYCODE_DPAD_RIGHT:
case KeyEvent.KEYCODE_DPAD_UP:
case KeyEvent.KEYCODE_ENTER:
return false;
}
return true;
}
private void showFilterView() {
if (mFilterView == null) {
mFilterView = (ContactListFilterView) getLayoutInflater().inflate(
R.layout.contact_list_filter_view, null);
mFilterView.getListView().setOnCreateContextMenuListener(this);
}
Uri uri = mGlobalSettingMap.getHideOfflineContacts() ? Imps.Contacts.CONTENT_URI_ONLINE_CONTACTS_BY
: Imps.Contacts.CONTENT_URI_CONTACTS_BY;
//uri = ContentUris.withAppendedId(uri, mProviderId);
//uri = ContentUris.withAppendedId(uri, mAccountId);
mFilterView.doFilter(uri, null);
try
{
setContentView(mFilterView);
mFilterView.requestFocus();
}
catch (Exception e) {
Log.d(ImApp.LOG_TAG,"error switching view",e);
}
mIsFiltering = true;
}
void showChatListView() {
if (mIsFiltering) {
setContentView(mActiveChatListView);
mActiveChatListView.requestFocus();
mActiveChatListView.invalidate();
mIsFiltering = false;
}
}
@Override
protected void onPause() {
super.onPause();
mApp.unregisterForConnEvents(mHandler);
}
@Override
protected void onResume() {
super.onResume();
((ImApp)getApplication()).startImServiceIfNeed(true);
mApp.registerForConnEvents(mHandler);
//mActiveChatListView.setAutoRefreshContacts(true);
}
@Override
protected void onDestroy() {
mDestroyed = true;
// set connection to null to unregister listeners.
mActiveChatListView.setConnection(null);
if (mGlobalSettingMap != null) {
mGlobalSettingMap.close();
}
super.onDestroy();
}
static void log(String msg) {
Log.d(ImApp.LOG_TAG, "<ContactListActivity> " + msg);
}
@Override
public void onCreateContextMenu(ContextMenu menu, View v, ContextMenuInfo menuInfo) {
boolean chatSelected = false;
boolean contactSelected = false;
Cursor contactCursor;
if (mIsFiltering) {
AdapterView.AdapterContextMenuInfo info = (AdapterContextMenuInfo) menuInfo;
mContextMenuHandler.mPosition = info.position;
contactSelected = true;
contactCursor = mFilterView.getContactAtPosition(info.position);
chatSelected = true;
} else {
if (menuInfo instanceof ExpandableListContextMenuInfo) {
ExpandableListContextMenuInfo info = (ExpandableListContextMenuInfo) menuInfo;
mContextMenuHandler.mPosition = info.packedPosition;
contactSelected = false;
chatSelected = mActiveChatListView.isConversationAtPosition(info.packedPosition);
contactCursor = null;
} else if (menuInfo instanceof AdapterContextMenuInfo) {
AdapterView.AdapterContextMenuInfo info = (AdapterContextMenuInfo) menuInfo;
mContextMenuHandler.mPosition = info.position;
contactSelected = false;
contactCursor = null;
chatSelected = mActiveChatListView.isConversationAtPosition(info.position);
} else
contactCursor = null;
}
/*
boolean allowBlock = true;
if (contactCursor != null) {
//XXX HACK: Yahoo! doesn't allow to block a friend. We can only block a temporary contact.
ProviderDef provider = mApp.getProvider(mProviderId);
if (Imps.ProviderNames.YAHOO.equals(provider.mName)) {
int type = contactCursor.getInt(contactCursor
.getColumnIndexOrThrow(Imps.Contacts.TYPE));
allowBlock = (type == Imps.Contacts.TYPE_TEMPORARY);
}
int nickNameIndex = contactCursor.getColumnIndexOrThrow(Imps.Contacts.NICKNAME);
menu.setHeaderTitle(contactCursor.getString(nickNameIndex));
}
*/
/*
BrandingResources brandingRes = mApp.getBrandingResource(mProviderId);
String menu_end_conversation = brandingRes
.getString(BrandingResourceIDs.STRING_MENU_END_CHAT);
String menu_view_profile = brandingRes
.getString(BrandingResourceIDs.STRING_MENU_VIEW_PROFILE);
String menu_block_contact = brandingRes
.getString(BrandingResourceIDs.STRING_MENU_BLOCK_CONTACT);
String menu_start_conversation = brandingRes
.getString(BrandingResourceIDs.STRING_MENU_START_CHAT);
String menu_delete_contact = brandingRes
.getString(BrandingResourceIDs.STRING_MENU_DELETE_CONTACT);
if (chatSelected) {
menu.add(0, MENU_END_CONVERSATION, 0, menu_end_conversation)
.setOnMenuItemClickListener(mContextMenuHandler);
menu.add(0, MENU_VIEW_PROFILE, 0, menu_view_profile)
.setIcon(R.drawable.ic_menu_my_profile)
.setOnMenuItemClickListener(mContextMenuHandler);
if (allowBlock) {
menu.add(0, MENU_BLOCK_CONTACT, 0, menu_block_contact)
.setOnMenuItemClickListener(mContextMenuHandler);
}
} else if (contactSelected) {
menu.add(0, MENU_START_CONVERSATION, 0, menu_start_conversation)
.setOnMenuItemClickListener(mContextMenuHandler);
menu.add(0, MENU_VIEW_PROFILE, 0, menu_view_profile)
.setIcon(R.drawable.ic_menu_view_profile)
.setOnMenuItemClickListener(mContextMenuHandler);
if (allowBlock) {
menu.add(0, MENU_BLOCK_CONTACT, 0, menu_block_contact)
.setOnMenuItemClickListener(mContextMenuHandler);
}
menu.add(0, MENU_DELETE_CONTACT, 0, menu_delete_contact)
.setIcon(android.R.drawable.ic_menu_delete)
.setOnMenuItemClickListener(mContextMenuHandler);
}*/
}
/*
void clearConnectionStatus() {
ContentResolver cr = getContentResolver();
ContentValues values = new ContentValues(3);
values.put(Imps.AccountStatus.ACCOUNT, mAccountId);
values.put(Imps.AccountStatus.PRESENCE_STATUS, Imps.Presence.OFFLINE);
values.put(Imps.AccountStatus.CONNECTION_STATUS, Imps.ConnectionStatus.OFFLINE);
// insert on the "account_status" uri actually replaces the existing value
cr.insert(Imps.AccountStatus.CONTENT_URI, values);
}*/
final class ContextMenuHandler implements android.view.MenuItem.OnMenuItemClickListener {
long mPosition;
@Override
public boolean onMenuItemClick(android.view.MenuItem item) {
if (item.getItemId() == MENU_END_CONVERSATION)
{
Cursor c = (Cursor)mActiveChatListView.getListView().getAdapter().getItem((int) mPosition);
long providerId = c.getLong(c.getColumnIndexOrThrow(Imps.Account.PROVIDER));
IImConnection conn = ((ImApp)getApplication()).getConnection(providerId);
mActiveChatListView.endChat(c, conn);
}
return false;
}
}
final class MyHandler extends SimpleAlertHandler {
public MyHandler(Activity activity) {
super(activity);
}
@Override
public void handleMessage(Message msg) {
if (msg.what == ImApp.EVENT_CONNECTION_DISCONNECTED) {
if (Log.isLoggable(ImApp.LOG_TAG, Log.DEBUG)) {
log("Handle event connection disconnected.");
}
promptDisconnectedEvent(msg);
}
super.handleMessage(msg);
}
}
@Override
public void onContentChanged() {
super.onContentChanged();
if (mActiveChatListView != null && mActiveChatListView.getListView().getCount() == 0)
{
View empty = findViewById(R.id.empty);
if (empty != null)
{
empty.setOnClickListener(new OnClickListener (){
@Override
public void onClick(View arg0) {
showContactsList ();
}
});
ListView list = (ListView) findViewById(R.id.chatsList);
list.setEmptyView(empty);
}
}
}
@Override
public 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));
long providerId = c.getLong(c.getColumnIndexOrThrow(Imps.Contacts.PROVIDER));
IImConnection conn = ((ImApp)getApplication()).getConnection(providerId);
try {
IChatSessionManager manager = conn.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);
if (menu.isShown())
menu.toggle();
startActivity(i);
} catch (RemoteException e) {
// mHandler.showServiceErrorAlert();
}
}
}
public void showProfile (Cursor c){}
}