blob: 3c9ac990301130b7bedc26c063f3055669e0a529 [file] [log] [blame]
/*
* Copyright (C) 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 android.app.Activity;
import android.app.AlertDialog;
import android.app.ListActivity;
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.Message;
import android.os.RemoteException;
import android.util.AttributeSet;
import android.util.Log;
import android.view.ContextMenu;
import android.view.LayoutInflater;
import android.view.Menu;
import android.view.MenuItem;
import android.view.View;
import android.view.ViewGroup;
import android.view.ContextMenu.ContextMenuInfo;
import android.widget.AdapterView;
import android.widget.CursorAdapter;
import android.widget.ListView;
import com.android.im.IImConnection;
import com.android.im.R;
import com.android.im.plugin.BrandingResourceIDs;
import com.android.im.provider.Imps;
public class LandingPage extends ListActivity implements View.OnCreateContextMenuListener {
private static final String TAG = ImApp.LOG_TAG;
private static final int ID_SIGN_IN = Menu.FIRST + 1;
private static final int ID_SIGN_OUT = Menu.FIRST + 2;
private static final int ID_EDIT_ACCOUNT = Menu.FIRST + 3;
private static final int ID_REMOVE_ACCOUNT = Menu.FIRST + 4;
private static final int ID_SIGN_OUT_ALL = Menu.FIRST + 5;
private static final int ID_ADD_ACCOUNT = Menu.FIRST + 6;
private static final int ID_VIEW_CONTACT_LIST = Menu.FIRST + 7;
private static final int ID_SETTINGS = Menu.FIRST + 8;
private ProviderAdapter mAdapter;
private Cursor mProviderCursor;
private ImApp mApp;
private SimpleAlertHandler mHandler;
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_ID_COLUMN = 0;
static final int PROVIDER_NAME_COLUMN = 1;
static final int PROVIDER_FULLNAME_COLUMN = 2;
static final int PROVIDER_CATEGORY_COLUMN = 3;
static final int ACTIVE_ACCOUNT_ID_COLUMN = 4;
static final int ACTIVE_ACCOUNT_USERNAME_COLUMN = 5;
static final int ACTIVE_ACCOUNT_PW_COLUMN = 6;
static final int ACTIVE_ACCOUNT_LOCKED = 7;
static final int ACTIVE_ACCOUNT_KEEP_SIGNED_IN = 8;
static final int ACCOUNT_PRESENCE_STATUS = 9;
static final int ACCOUNT_CONNECTION_STATUS = 10;
@Override
protected void onCreate(Bundle icicle) {
super.onCreate(icicle);
setTitle(R.string.landing_page_title);
mApp = ImApp.getApplication(this);
mHandler = new MyHandler(this);
ImPluginHelper.getInstance(this).loadAvaiablePlugins();
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);
mAdapter = new ProviderAdapter(this, mProviderCursor);
setListAdapter(mAdapter);
registerForContextMenu(getListView());
}
@Override
protected void onPause() {
mHandler.unregisterForBroadcastEvents();
super.onPause();
}
@Override
protected void onResume() {
super.onResume();
mHandler.registerForBroadcastEvents();
}
private void signIn(long accountId) {
if (accountId == 0) {
Log.w(TAG, "signIn: account id is 0, bail");
return;
}
boolean isAccountEditible = mProviderCursor.getInt(ACTIVE_ACCOUNT_LOCKED) == 0;
if (isAccountEditible && mProviderCursor.isNull(ACTIVE_ACCOUNT_PW_COLUMN)) {
// no password, edit the account
if (Log.isLoggable(TAG, Log.DEBUG)) log("no pw for account " + accountId);
Intent intent = getEditAccountIntent();
startActivity(intent);
return;
}
Intent intent = new Intent(this, SigningInActivity.class);
intent.setData(ContentUris.withAppendedId(Imps.Account.CONTENT_URI, accountId));
startActivity(intent);
}
boolean isSigningIn(Cursor cursor) {
int connectionStatus = cursor.getInt(ACCOUNT_CONNECTION_STATUS);
return connectionStatus == Imps.ConnectionStatus.CONNECTING;
}
private boolean isSignedIn(Cursor cursor) {
int connectionStatus = cursor.getInt(ACCOUNT_CONNECTION_STATUS);
return connectionStatus == Imps.ConnectionStatus.ONLINE;
}
private boolean allAccountsSignedOut() {
if(!mProviderCursor.moveToFirst()) {
return false;
}
do {
if (isSignedIn(mProviderCursor)) {
return false;
}
} while (mProviderCursor.moveToNext()) ;
return true;
}
private void signoutAll() {
DialogInterface.OnClickListener confirmListener
= new DialogInterface.OnClickListener(){
public void onClick(DialogInterface dialog, int whichButton) {
do {
long accountId = mProviderCursor.getLong(ACTIVE_ACCOUNT_ID_COLUMN);
signOut(accountId);
} while (mProviderCursor.moveToNext()) ;
}
};
new AlertDialog.Builder(this)
.setTitle(R.string.confirm)
.setMessage(R.string.signout_all_confirm_message)
.setPositiveButton(R.string.yes, confirmListener) // default button
.setNegativeButton(R.string.no, null)
.setCancelable(true)
.show();
}
private void signOut(long accountId) {
if (accountId == 0) {
Log.w(TAG, "signOut: account id is 0, bail");
return;
}
try {
IImConnection conn = mApp.getConnectionByAccount(accountId);
if (conn != null) {
conn.logout();
}
} catch (RemoteException ex) {
Log.e(TAG, "signOut failed", ex);
}
}
@Override
public boolean onPrepareOptionsMenu(Menu menu) {
super.onPrepareOptionsMenu(menu);
menu.findItem(ID_SIGN_OUT_ALL).setVisible(!allAccountsSignedOut());
return true;
}
@Override
public boolean onCreateOptionsMenu(Menu menu) {
menu.add(0, ID_SIGN_OUT_ALL, 0, R.string.menu_sign_out_all)
.setIcon(android.R.drawable.ic_menu_close_clear_cancel);
return true;
}
@Override
public boolean onOptionsItemSelected(MenuItem item) {
switch (item.getItemId()) {
case ID_SIGN_OUT_ALL:
signoutAll();
return true;
}
return super.onOptionsItemSelected(item);
}
@Override
public void onCreateContextMenu(ContextMenu menu, View v, ContextMenuInfo menuInfo) {
AdapterView.AdapterContextMenuInfo info;
try {
info = (AdapterView.AdapterContextMenuInfo) menuInfo;
} catch (ClassCastException e) {
Log.e(TAG, "bad menuInfo", e);
return;
}
Cursor providerCursor = (Cursor) getListAdapter().getItem(info.position);
menu.setHeaderTitle(providerCursor.getString(PROVIDER_FULLNAME_COLUMN));
if (providerCursor.isNull(ACTIVE_ACCOUNT_ID_COLUMN)) {
menu.add(0, ID_ADD_ACCOUNT, 0, R.string.menu_add_account);
return;
}
long providerId = providerCursor.getLong(PROVIDER_ID_COLUMN);
boolean isLoggingIn = isSigningIn(providerCursor);
boolean isLoggedIn = isSignedIn(providerCursor);
BrandingResources brandingRes = mApp.getBrandingResource(providerId);
if (!isLoggedIn) {
menu.add(0, ID_SIGN_IN, 0, R.string.sign_in).setIcon(com.android.internal.R.drawable.ic_menu_login);
} else {
menu.add(0, ID_VIEW_CONTACT_LIST, 0,
brandingRes.getString(BrandingResourceIDs.STRING_MENU_CONTACT_LIST));
menu.add(0, ID_SIGN_OUT, 0, R.string.menu_sign_out)
.setIcon(android.R.drawable.ic_menu_close_clear_cancel);
}
boolean isAccountEditible = providerCursor.getInt(ACTIVE_ACCOUNT_LOCKED) == 0;
if (isAccountEditible && !isLoggingIn && !isLoggedIn) {
menu.add(0, ID_EDIT_ACCOUNT, 0, R.string.menu_edit_account)
.setIcon(android.R.drawable.ic_menu_edit);
menu.add(0, ID_REMOVE_ACCOUNT, 0, R.string.menu_remove_account)
.setIcon(android.R.drawable.ic_menu_delete);
}
// always add a settings menu item
menu.add(0, ID_SETTINGS, 0, R.string.menu_settings);
}
@Override
public boolean onContextItemSelected(MenuItem item) {
AdapterView.AdapterContextMenuInfo info;
try {
info = (AdapterView.AdapterContextMenuInfo) item.getMenuInfo();
} catch (ClassCastException e) {
Log.e(TAG, "bad menuInfo", e);
return false;
}
long providerId = info.id;
Cursor providerCursor = (Cursor) getListAdapter().getItem(info.position);
long accountId = providerCursor.getLong(ACTIVE_ACCOUNT_ID_COLUMN);
switch (item.getItemId()) {
case ID_EDIT_ACCOUNT:
{
startActivity(getEditAccountIntent());
return true;
}
case ID_REMOVE_ACCOUNT:
{
Uri accountUri = ContentUris.withAppendedId(Imps.Account.CONTENT_URI, accountId);
getContentResolver().delete(accountUri, null, null);
// Requery the cursor to force refreshing screen
providerCursor.requery();
return true;
}
case ID_VIEW_CONTACT_LIST:
{
Intent intent = getViewContactsIntent();
startActivity(intent);
return true;
}
case ID_ADD_ACCOUNT:
{
startActivity(getCreateAccountIntent());
return true;
}
case ID_SIGN_IN:
{
signIn(accountId);
return true;
}
case ID_SIGN_OUT:
{
// TODO: progress bar
signOut(accountId);
return true;
}
case ID_SETTINGS:
{
Intent intent = new Intent(Intent.ACTION_VIEW, Imps.ProviderSettings.CONTENT_URI);
intent.addCategory(getProviderCategory(providerCursor));
intent.putExtra("providerId", providerId);
startActivity(intent);
return true;
}
}
return false;
}
@Override
protected void onListItemClick(ListView l, View v, int position, long id) {
Intent intent = null;
mProviderCursor.moveToPosition(position);
if (mProviderCursor.isNull(ACTIVE_ACCOUNT_ID_COLUMN)) {
// add account
intent = getCreateAccountIntent();
} else {
int state = mProviderCursor.getInt(ACCOUNT_CONNECTION_STATUS);
long accountId = mProviderCursor.getLong(ACTIVE_ACCOUNT_ID_COLUMN);
if (state == Imps.ConnectionStatus.OFFLINE) {
boolean isKeepSignedIn = mProviderCursor.getInt(ACTIVE_ACCOUNT_KEEP_SIGNED_IN) != 0;
boolean isAccountEditible = mProviderCursor.getInt(ACTIVE_ACCOUNT_LOCKED) == 0;
if (isKeepSignedIn) {
signIn(accountId);
} else if(isAccountEditible) {
intent = getEditAccountIntent();
}
} else if (state == Imps.ConnectionStatus.CONNECTING) {
signIn(accountId);
} else {
intent = getViewContactsIntent();
}
}
if (intent != null) {
startActivity(intent);
}
}
Intent getCreateAccountIntent() {
Intent intent = new Intent();
intent.setAction(Intent.ACTION_INSERT);
long providerId = mProviderCursor.getLong(PROVIDER_ID_COLUMN);
intent.setData(ContentUris.withAppendedId(Imps.Provider.CONTENT_URI, providerId));
intent.addCategory(getProviderCategory(mProviderCursor));
return intent;
}
Intent getEditAccountIntent() {
Intent intent = new Intent(Intent.ACTION_EDIT,
ContentUris.withAppendedId(Imps.Account.CONTENT_URI,
mProviderCursor.getLong(ACTIVE_ACCOUNT_ID_COLUMN)));
intent.addCategory(getProviderCategory(mProviderCursor));
return intent;
}
Intent getViewContactsIntent() {
Intent intent = new Intent(Intent.ACTION_VIEW);
intent.setData(Imps.Contacts.CONTENT_URI);
intent.addCategory(getProviderCategory(mProviderCursor));
intent.putExtra("accountId", mProviderCursor.getLong(ACTIVE_ACCOUNT_ID_COLUMN));
return intent;
}
private String getProviderCategory(Cursor cursor) {
return cursor.getString(PROVIDER_CATEGORY_COLUMN);
}
static void log(String msg) {
Log.d(TAG, "[LandingPage]" + msg);
}
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, LandingPage.this);
}
return null;
}
}
private final class ProviderAdapter extends CursorAdapter {
private LayoutInflater mInflater;
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, parent, false);
view.init(cursor);
return view;
}
@Override
public void bindView(View view, Context context, Cursor cursor) {
((ProviderListItem) view).bindView(cursor);
}
}
private final static class MyHandler extends SimpleAlertHandler {
public MyHandler(Activity activity) {
super(activity);
}
@Override
public void handleMessage(Message msg) {
if (msg.what == ImApp.EVENT_CONNECTION_DISCONNECTED) {
promptDisconnectedEvent(msg);
}
super.handleMessage(msg);
}
}
}