package org.yaxim.androidclient.chat;
import java.util.List;
import java.util.zip.CRC32;
import java.util.zip.Checksum;
import org.yaxim.androidclient.R;
import org.yaxim.androidclient.YaximApplication;
import org.yaxim.androidclient.data.ChatProvider.ChatConstants;
import org.yaxim.androidclient.data.ChatHelper;
import org.yaxim.androidclient.data.ChatRoomHelper;
import org.yaxim.androidclient.dialogs.ConfirmDialog;
import org.yaxim.androidclient.dialogs.EditMUCDialog;
import org.yaxim.androidclient.service.IXMPPMucService;
import org.yaxim.androidclient.service.ParcelablePresence;
import org.yaxim.androidclient.service.XMPPService;
import org.yaxim.androidclient.util.XMPPHelper;
import android.app.AlertDialog;
import android.content.ComponentName;
import android.content.Context;
import android.content.DialogInterface;
import android.content.Intent;
import android.content.ServiceConnection;
import android.content.DialogInterface.OnClickListener;
import android.database.Cursor;
import android.graphics.Color;
import android.net.Uri;
import android.os.Bundle;
import android.os.IBinder;
import android.util.Log;
import android.util.TypedValue;
import android.view.View;
import android.view.ViewGroup;
import android.widget.AdapterView;
import android.widget.AdapterView.OnItemClickListener;
import android.widget.AdapterView.OnItemLongClickListener;
import android.widget.ArrayAdapter;
import android.widget.ImageView;
import android.widget.TextView;
import android.widget.Toast;
import com.actionbarsherlock.view.MenuInflater;
public class MUCChatWindow extends ChatWindow {
private static final String TAG = "yaxim.MUCChatWindow";
private Intent mMucServiceIntent;
private ServiceConnection mMucServiceConnection;
private XMPPMucServiceAdapter mMucServiceAdapter;
private String myNick;
@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
// fill in nickname on tap
getListView().setOnItemClickListener(new OnItemClickListener() {
@Override
public void onItemClick(AdapterView<?> parent,
View view, int position, long id) {
Cursor c = (Cursor)parent.getItemAtPosition(position);
addNicknameToInput(c.getString(c.getColumnIndex(ChatConstants.RESOURCE)));
}});
XMPPHelper.setStaticNFC(this, "xmpp:" + mWithJabberID + "?join");
}
@Override
protected void registerXMPPService() {
super.registerXMPPService();
mMucServiceIntent = new Intent(this, XMPPService.class);
Uri dtaUri = Uri.parse(mWithJabberID+"?chat");
mMucServiceIntent.setData(dtaUri);
mMucServiceIntent.setAction("org.yaxim.androidclient.XMPPSERVICE");
mMucServiceConnection = new ServiceConnection() {
public void onServiceConnected(ComponentName name, IBinder service) {
mMucServiceAdapter = new XMPPMucServiceAdapter(
IXMPPMucService.Stub.asInterface(service),
mWithJabberID);
myNick = mMucServiceAdapter.getMyMucNick();
mChatAdapter.mScreenName = myNick;
supportInvalidateOptionsMenu();
getListView().invalidateViews();
}
public void onServiceDisconnected(ComponentName name) {
}
};
}
@Override
protected void unbindXMPPService() {
super.unbindXMPPService();
try {
unbindService(mMucServiceConnection);
} catch (IllegalArgumentException e) {
Log.e(TAG, "Service wasn't bound!");
}
}
@Override
protected void bindXMPPService() {
super.bindXMPPService();
bindService(mMucServiceIntent, mMucServiceConnection, BIND_AUTO_CREATE);
}
@Override
public boolean onCreateOptionsMenu(com.actionbarsherlock.view.Menu menu) {
Log.d(TAG, "creating options menu, we're a muc");
MenuInflater inflater = getSupportMenuInflater();
inflater.inflate(R.menu.muc_options, menu);
inflater.inflate(R.menu.roster_item_contextmenu, menu);
return true;
}
@Override
public boolean onOptionsItemSelected(com.actionbarsherlock.view.MenuItem item) {
Log.d(TAG, "options item selected");
switch (item.getItemId()) {
case R.id.chat_optionsmenu_userlist:
showUserList();
return true;
case R.id.roster_contextmenu_muc_edit:
new EditMUCDialog(this, mWithJabberID).dontOpen().show();
return true;
case R.id.roster_contextmenu_muc_share:
XMPPHelper.shareLink(this, R.string.roster_contextmenu_contact_share,
XMPPHelper.createMucLinkHTTPS(mWithJabberID));
return true;
case R.id.roster_contextmenu_muc_leave:
ConfirmDialog.show(this, R.string.roster_contextmenu_muc_leave,
getString(R.string.muc_leave_question, mWithJabberID), mWithJabberID,
new ConfirmDialog.Ok() {
@Override
public void ok(final String jid) {
if (ChatRoomHelper.removeRoom(MUCChatWindow.this, jid))
ChatRoomHelper.syncDbRooms(MUCChatWindow.this);
// XXX: if we do not unbind here, we will leak the service
unbindXMPPService();
finish();
}
});
return true;
default:
return super.onOptionsItemSelected(item);
}
}
private void addNicknameToInput(String nickname) {
if (nickname.equalsIgnoreCase(myNick))
return;
int cursor_position = mChatInput.getSelectionStart();
String postfix = (cursor_position == 0) ? ": " : " ";
mChatInput.getText().insert(cursor_position, nickname + postfix);
}
private void showUserList() {
if (mMucServiceAdapter == null)
return;
final List<ParcelablePresence> users = mMucServiceAdapter.getUserList();
if (users == null) {
Toast.makeText(this, R.string.Global_authenticate_first, Toast.LENGTH_SHORT).show();
return;
}
AlertDialog.Builder dialogBuilder = new AlertDialog.Builder(MUCChatWindow.this)
.setTitle(getString(R.string.chat_muc_userlist, mWithJabberID))
.setNegativeButton(android.R.string.cancel, null);
PresenceArrayAdapter adapter = new PresenceArrayAdapter(MUCChatWindow.this, users);
Log.d(TAG, "adapter has values: "+adapter.getCount());
dialogBuilder.setAdapter(adapter, new OnClickListener() {
@Override
public void onClick(DialogInterface dialog, int which) {
addNicknameToInput(users.get(which).resource);
}
});
AlertDialog dialog = dialogBuilder.create();
dialog.getListView().setOnItemLongClickListener(new OnItemLongClickListener() {
@Override
public boolean onItemLongClick(AdapterView<?> parent,
View view, int position, long id) {
String nickname = users.get(position).resource;
ChatHelper.startChatActivity(MUCChatWindow.this, mWithJabberID+"/"+nickname,
String.format("%s (%s)", nickname, mUserScreenName), null);
return true;
}});
// TODO: this is a fix for broken theming on android 2.x, fix more cleanly!
if(android.os.Build.VERSION.SDK_INT < android.os.Build.VERSION_CODES.HONEYCOMB) {
boolean is_dark = (mConfig.getTheme() == R.style.YaximDarkTheme);
dialog.getListView().setBackgroundColor(is_dark ? Color.BLACK : Color.WHITE);
}
dialog.show();
}
public String jid2nickname(String jid, String resource) {
return resource;
}
@Override
public void nick2Color(String nick, TypedValue tv) {
if (nick == null || nick.length() == 0) // no color for empty nickname
return;
Checksum nickCRC = new CRC32();
nickCRC.update(nick.getBytes(), 0, nick.length());
int nickInt = (int)nickCRC.getValue();
int theme = mConfig.getTheme();
// default HSV is for dark theme, bright and light
float h = Math.abs(nickInt % 360), s = 0.5f, v= 0.9f;
if (theme == R.style.YaximDarkTheme) {
// make blue nicks a bit lighter on dark
if(h<=255.0f && h>=225.0f)
s=0.4f;
} else { // light theme: strong and darker nick color
s=0.85f;
v=0.6f;
}
tv.data = Color.HSVToColor(0xFF, new float[]{h, s, v});
}
private class PresenceArrayAdapter extends ArrayAdapter<ParcelablePresence> {
TypedValue tv = new TypedValue();
public PresenceArrayAdapter(Context context, List<ParcelablePresence> pp) {
super(context, R.layout.mainchild_row, pp);
}
@Override
public View getView(int position, View convertView, ViewGroup parent) {
ParcelablePresence pp = getItem(position);
if (convertView == null)
convertView = getLayoutInflater().inflate(R.layout.mainchild_row, parent, false);
TextView nick = ((TextView)convertView.findViewById(R.id.roster_screenname));
TextView statusmsg = ((TextView)convertView.findViewById(R.id.roster_statusmsg));
nick.setText(pp.resource);
nick2Color(pp.resource, tv);
nick.setTextColor(tv.data);
nick.setTypeface(null, android.graphics.Typeface.BOLD);
boolean hasStatus = pp.status != null && pp.status.length() > 0;
statusmsg.setText(pp.status);
statusmsg.setVisibility(hasStatus ? View.VISIBLE : View.GONE);
((ImageView)convertView.findViewById(R.id.roster_icon)).setImageResource(pp.status_mode.getDrawableId());
return convertView;
}
}
}