Home | History | Annotate | Download | only in app
      1 /*
      2  * Copyright (C) 2008 Esmertec AG.
      3  * Copyright (C) 2008 The Android Open Source Project
      4  *
      5  * Licensed under the Apache License, Version 2.0 (the "License"); you may not
      6  * use this file except in compliance with the License. You may obtain a copy of
      7  * the License at
      8  *
      9  * http://www.apache.org/licenses/LICENSE-2.0
     10  *
     11  * Unless required by applicable law or agreed to in writing, software
     12  * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
     13  * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
     14  * License for the specific language governing permissions and limitations under
     15  * the License.
     16  */
     17 package com.android.im.app;
     18 
     19 import static com.android.im.service.ImServiceConstants.ACTION_MANAGE_SUBSCRIPTION;
     20 import static com.android.im.service.ImServiceConstants.EXTRA_INTENT_ACCOUNT_ID;
     21 import static com.android.im.service.ImServiceConstants.EXTRA_INTENT_FROM_ADDRESS;
     22 import static com.android.im.service.ImServiceConstants.EXTRA_INTENT_PROVIDER_ID;
     23 import static com.android.im.service.ImServiceConstants.EXTRA_INTENT_SHOW_MULTIPLE;
     24 
     25 import com.android.im.IChatSession;
     26 import com.android.im.R;
     27 import com.android.im.app.adapter.ChatListenerAdapter;
     28 import com.android.im.plugin.BrandingResourceIDs;
     29 import com.android.im.provider.Imps;
     30 
     31 import android.app.Activity;
     32 import android.app.AlertDialog;
     33 import android.content.ContentResolver;
     34 import android.content.ContentUris;
     35 import android.content.DialogInterface;
     36 import android.content.Intent;
     37 import android.database.Cursor;
     38 import android.graphics.drawable.Drawable;
     39 import android.net.Uri;
     40 import android.os.Bundle;
     41 import android.os.Handler;
     42 import android.os.RemoteException;
     43 import android.view.KeyEvent;
     44 import android.view.LayoutInflater;
     45 import android.view.Menu;
     46 import android.view.MenuInflater;
     47 import android.view.MenuItem;
     48 import android.view.View;
     49 import android.view.ViewGroup;
     50 import android.view.Window;
     51 import android.widget.ImageView;
     52 import android.widget.SimpleAdapter;
     53 import android.widget.Toast;
     54 
     55 import java.util.ArrayList;
     56 import java.util.HashMap;
     57 import java.util.List;
     58 import java.util.Map;
     59 
     60 public class NewChatActivity extends Activity {
     61 
     62     private static final int REQUEST_PICK_CONTACTS = RESULT_FIRST_USER + 1;
     63 
     64     ImApp mApp;
     65 
     66     ChatView mChatView;
     67     SimpleAlertHandler mHandler;
     68 
     69     private AlertDialog mSmileyDialog;
     70     private ChatSwitcher mChatSwitcher;
     71 
     72     private LayoutInflater mInflater;
     73 
     74     @Override
     75     protected void onCreate(Bundle icicle) {
     76         super.onCreate(icicle);
     77 
     78         requestWindowFeature(Window.FEATURE_NO_TITLE);
     79 
     80         setContentView(R.layout.chat_view);
     81 
     82         mChatView = (ChatView) findViewById(R.id.chatView);
     83         mHandler = mChatView.mHandler;
     84         mInflater = LayoutInflater.from(this);
     85 
     86         mApp = ImApp.getApplication(this);
     87         mChatSwitcher = new ChatSwitcher(this, mHandler, mApp, mInflater, null);
     88 
     89         final Handler handler = new Handler();
     90         mApp.callWhenServiceConnected(handler, new Runnable() {
     91             public void run() {
     92                 resolveIntent(getIntent());
     93             }
     94         });
     95     }
     96 
     97     @Override
     98     protected void onResume() {
     99         super.onResume();
    100         mChatView.onResume();
    101     }
    102 
    103     @Override
    104     protected void onPause() {
    105         mChatView.onPause();
    106         super.onPause();
    107     }
    108 
    109     @Override
    110     protected void onNewIntent(Intent intent) {
    111         resolveIntent(intent);
    112     }
    113 
    114     void resolveIntent(Intent intent) {
    115         if (requireOpenDashboardOnStart(intent)) {
    116             long providerId = intent.getLongExtra(EXTRA_INTENT_PROVIDER_ID, -1L);
    117             final long accountId = intent.getLongExtra(EXTRA_INTENT_ACCOUNT_ID, -1L);
    118             if (providerId == -1L || accountId == -1L) {
    119                 finish();
    120             } else {
    121                 mChatSwitcher.open();
    122             }
    123             return;
    124         }
    125 
    126         if (ACTION_MANAGE_SUBSCRIPTION.equals(intent.getAction())) {
    127             long providerId = intent.getLongExtra(EXTRA_INTENT_PROVIDER_ID, -1);
    128             String from = intent.getStringExtra(EXTRA_INTENT_FROM_ADDRESS);
    129             if ((providerId == -1) || (from == null)) {
    130                 finish();
    131             } else {
    132                 mChatView.bindSubscription(providerId, from);
    133             }
    134         } else {
    135             Uri data = intent.getData();
    136             String type = getContentResolver().getType(data);
    137             if (Imps.Chats.CONTENT_ITEM_TYPE.equals(type)) {
    138                 mChatView.bindChat(ContentUris.parseId(data));
    139             } else if (Imps.Invitation.CONTENT_ITEM_TYPE.equals(type)) {
    140                 mChatView.bindInvitation(ContentUris.parseId(data));
    141             }
    142         }
    143     }
    144 
    145     @Override
    146     public boolean onCreateOptionsMenu(Menu menu) {
    147         MenuInflater inflater = getMenuInflater();
    148         inflater.inflate(R.menu.chat_screen_menu, menu);
    149 
    150         long providerId = mChatView.getProviderId();
    151         BrandingResources brandingRes = mApp.getBrandingResource(providerId);
    152         menu.findItem(R.id.menu_view_friend_list).setTitle(
    153                 brandingRes.getString(BrandingResourceIDs.STRING_MENU_CONTACT_LIST));
    154         menu.findItem(R.id.menu_switch_chats).setTitle(
    155                 brandingRes.getString(BrandingResourceIDs.STRING_MENU_SWITCH_CHATS));
    156         menu.findItem(R.id.menu_insert_smiley).setTitle(
    157                 brandingRes.getString(BrandingResourceIDs.STRING_MENU_INSERT_SMILEY));
    158         menu.findItem(R.id.menu_end_conversation).setTitle(
    159                 brandingRes.getString(BrandingResourceIDs.STRING_MENU_END_CHAT));
    160         menu.findItem(R.id.menu_view_profile).setTitle(
    161                 brandingRes.getString(BrandingResourceIDs.STRING_MENU_VIEW_PROFILE));
    162         menu.findItem(R.id.menu_block_contact).setTitle(
    163                 brandingRes.getString(BrandingResourceIDs.STRING_MENU_BLOCK_CONTACT));
    164         return true;
    165     }
    166 
    167     @Override
    168     public boolean onPrepareOptionsMenu(Menu menu) {
    169         super.onPrepareOptionsMenu(menu);
    170 
    171         //XXX hide the invite menu, group chat is not supported by the server.
    172         menu.findItem(R.id.menu_invite_contact).setVisible(false);
    173 
    174         //XXX HACK: Yahoo! doesn't allow to block a friend. We can only block a temporary contact.
    175         ProviderDef provider = mApp.getProvider(mChatView.getProviderId());
    176         if ((provider != null) && Imps.ProviderNames.YAHOO.equals(provider.mName)) {
    177             if (Imps.Contacts.TYPE_TEMPORARY != mChatView.mType) {
    178                 menu.findItem(R.id.menu_block_contact).setVisible(false);
    179             }
    180         }
    181         return true;
    182     }
    183 
    184     @Override
    185     public boolean onOptionsItemSelected(MenuItem item) {
    186         switch (item.getItemId()) {
    187             case R.id.menu_view_friend_list:
    188                 finish();
    189                 showRosterScreen();
    190                 return true;
    191 
    192             case R.id.menu_insert_smiley:
    193                 showSmileyDialog();
    194                 return true;
    195 
    196             case R.id.menu_end_conversation:
    197                 mChatView.closeChatSession();
    198                 return true;
    199 
    200             case R.id.menu_switch_chats:
    201                 if (mChatSwitcher.isOpen()) {
    202                     mChatSwitcher.close();
    203                 } else {
    204                     mChatSwitcher.open();
    205                 }
    206 
    207                 return true;
    208 
    209             case R.id.menu_invite_contact:
    210                 startContactPicker();
    211                 return true;
    212 
    213             case R.id.menu_view_profile:
    214                 mChatView.viewProfile();
    215                 return true;
    216 
    217             case R.id.menu_block_contact:
    218                 mChatView.blockContact();
    219                 return true;
    220 
    221             case R.id.menu_prev_chat:
    222                 switchChat(-1);
    223                 return true;
    224 
    225             case R.id.menu_next_chat:
    226                 switchChat(1);
    227                 return true;
    228 
    229             case R.id.menu_quick_switch_0:
    230             case R.id.menu_quick_switch_1:
    231             case R.id.menu_quick_switch_2:
    232             case R.id.menu_quick_switch_3:
    233             case R.id.menu_quick_switch_4:
    234             case R.id.menu_quick_switch_5:
    235             case R.id.menu_quick_switch_6:
    236             case R.id.menu_quick_switch_7:
    237             case R.id.menu_quick_switch_8:
    238             case R.id.menu_quick_switch_9:
    239                 mChatSwitcher.handleShortcut(item.getAlphabeticShortcut());
    240                 return true;
    241         }
    242 
    243         return super.onOptionsItemSelected(item);
    244     }
    245 
    246     @Override
    247     public boolean dispatchKeyEvent(KeyEvent event) {
    248         if (event.getKeyCode() == KeyEvent.KEYCODE_BACK
    249                 && event.getAction() == KeyEvent.ACTION_DOWN) {
    250             mChatView.closeChatSessionIfInactive();
    251         }
    252         return super.dispatchKeyEvent(event);
    253     }
    254 
    255     /**
    256      * Check whether we are asked to open Dashboard on startup.
    257      */
    258     private boolean requireOpenDashboardOnStart(Intent intent) {
    259         return intent.getBooleanExtra(EXTRA_INTENT_SHOW_MULTIPLE, false);
    260     }
    261 
    262     private void showRosterScreen() {
    263         Intent intent = new Intent(Intent.ACTION_VIEW);
    264         intent.setClass(this, ContactListActivity.class);
    265         intent.putExtra(EXTRA_INTENT_ACCOUNT_ID, mChatView.getAccountId());
    266         startActivity(intent);
    267     }
    268 
    269     private void showSmileyDialog() {
    270         if (mSmileyDialog == null) {
    271             long providerId = mChatView.getProviderId();
    272 
    273             final BrandingResources brandingRes = mApp.getBrandingResource(providerId);
    274             int[] icons = brandingRes.getSmileyIcons();
    275             String[] names = brandingRes.getStringArray(
    276                     BrandingResourceIDs.STRING_ARRAY_SMILEY_NAMES);
    277             final String[] texts = brandingRes.getStringArray(
    278                     BrandingResourceIDs.STRING_ARRAY_SMILEY_TEXTS);
    279 
    280             final int N = names.length;
    281 
    282             List<Map<String, ?>> entries = new ArrayList<Map<String, ?>>();
    283             for (int i = 0; i < N; i++) {
    284                 // We might have different ASCII for the same icon, skip it if
    285                 // the icon is already added.
    286                 boolean added = false;
    287                 for (int j = 0; j < i; j++) {
    288                     if (icons[i] == icons[j]) {
    289                         added = true;
    290                         break;
    291                     }
    292                 }
    293                 if (!added) {
    294                     HashMap<String, Object> entry = new HashMap<String, Object>();
    295 
    296                     entry. put("icon", icons[i]);
    297                     entry. put("name", names[i]);
    298                     entry.put("text", texts[i]);
    299 
    300                     entries.add(entry);
    301                 }
    302             }
    303 
    304             final SimpleAdapter a = new SimpleAdapter(
    305                     this,
    306                     entries,
    307                     R.layout.smiley_menu_item,
    308                     new String[] {"icon", "name", "text"},
    309                     new int[] {R.id.smiley_icon, R.id.smiley_name, R.id.smiley_text});
    310             SimpleAdapter.ViewBinder viewBinder = new SimpleAdapter.ViewBinder() {
    311                 public boolean setViewValue(View view, Object data, String textRepresentation) {
    312                     if (view instanceof ImageView) {
    313                         Drawable img = brandingRes.getSmileyIcon((Integer)data);
    314                         ((ImageView)view).setImageDrawable(img);
    315                         return true;
    316                     }
    317                     return false;
    318                 }
    319             };
    320             a.setViewBinder(viewBinder);
    321 
    322             AlertDialog.Builder b = new AlertDialog.Builder(this);
    323 
    324             b.setTitle(brandingRes.getString(
    325                     BrandingResourceIDs.STRING_MENU_INSERT_SMILEY));
    326 
    327             b.setCancelable(true);
    328             b.setAdapter(a, new DialogInterface.OnClickListener() {
    329                 public final void onClick(DialogInterface dialog, int which) {
    330                     HashMap<String, Object> item = (HashMap<String, Object>) a.getItem(which);
    331                     mChatView.insertSmiley((String)item.get("text"));
    332                 }
    333             });
    334 
    335             mSmileyDialog = b.create();
    336         }
    337 
    338         mSmileyDialog.show();
    339     }
    340 
    341     private void switchChat(int delta) {
    342         long providerId = mChatView.getProviderId();
    343         long accountId = mChatView.getAccountId();
    344         String contact = mChatView.getUserName();
    345 
    346         mChatSwitcher.rotateChat(delta, contact, accountId, providerId);
    347     }
    348 
    349     private void startContactPicker() {
    350         Uri.Builder builder = Imps.Contacts.CONTENT_URI_ONLINE_CONTACTS_BY.buildUpon();
    351         ContentUris.appendId(builder, mChatView.getProviderId());
    352         ContentUris.appendId(builder, mChatView.getAccountId());
    353         Uri data = builder.build();
    354 
    355         try {
    356             Intent i = new Intent(Intent.ACTION_PICK, data);
    357             i.putExtra(ContactsPickerActivity.EXTRA_EXCLUDED_CONTACTS,
    358                     mChatView.getCurrentChatSession().getPariticipants());
    359             startActivityForResult(i, REQUEST_PICK_CONTACTS);
    360         } catch (RemoteException e) {
    361             mHandler.showServiceErrorAlert();
    362         }
    363     }
    364 
    365     @Override
    366     protected void onActivityResult(int requestCode, int resultCode,
    367             Intent data) {
    368         if (resultCode == RESULT_OK) {
    369             if (requestCode == REQUEST_PICK_CONTACTS) {
    370                 String username = data.getStringExtra(
    371                         ContactsPickerActivity.EXTRA_RESULT_USERNAME);
    372                 try {
    373                     IChatSession chatSession = mChatView.getCurrentChatSession();
    374                     if (chatSession.isGroupChatSession()) {
    375                         chatSession.inviteContact(username);
    376                         showInvitationHasSent(username);
    377                     } else {
    378                         chatSession.convertToGroupChat();
    379                         new ContactInvitor(chatSession, username).start();
    380                     }
    381                 } catch (RemoteException e) {
    382                     mHandler.showServiceErrorAlert();
    383                 }
    384             }
    385         }
    386     }
    387 
    388     void showInvitationHasSent(String contact) {
    389         Toast.makeText(NewChatActivity.this,
    390                 getString(R.string.invitation_sent_prompt, contact),
    391                 Toast.LENGTH_SHORT).show();
    392     }
    393 
    394     private class ContactInvitor extends ChatListenerAdapter {
    395         private final IChatSession mChatSession;
    396         String mContact;
    397 
    398         public ContactInvitor(IChatSession session, String data) {
    399             mChatSession = session;
    400             mContact = data;
    401         }
    402 
    403         @Override
    404         public void onConvertedToGroupChat(IChatSession ses) {
    405             try {
    406                 final long chatId = mChatSession.getId();
    407                 mChatSession.inviteContact(mContact);
    408                 mHandler.post(new Runnable(){
    409                     public void run() {
    410                         mChatView.bindChat(chatId);
    411                         showInvitationHasSent(mContact);
    412                     }
    413                 });
    414                 mChatSession.unregisterChatListener(this);
    415             } catch (RemoteException e) {
    416                 mHandler.showServiceErrorAlert();
    417             }
    418         }
    419 
    420         public void start() throws RemoteException {
    421             mChatSession.registerChatListener(this);
    422         }
    423     }
    424 }
    425