1package eu.siacs.conversations.ui;
2
3import java.io.UnsupportedEncodingException;
4import java.net.URLDecoder;
5import java.util.ArrayList;
6import java.util.Collections;
7import java.util.Comparator;
8import java.util.List;
9import java.util.Locale;
10
11import eu.siacs.conversations.R;
12import eu.siacs.conversations.entities.Account;
13import eu.siacs.conversations.entities.Contact;
14import eu.siacs.conversations.entities.Conversation;
15import eu.siacs.conversations.utils.UIHelper;
16import eu.siacs.conversations.utils.Validator;
17import android.net.Uri;
18import android.os.Bundle;
19import android.text.Editable;
20import android.text.TextWatcher;
21import android.util.Log;
22import android.view.LayoutInflater;
23import android.view.Menu;
24import android.view.MenuItem;
25import android.view.View;
26import android.view.ViewGroup;
27import android.widget.AdapterView;
28import android.widget.AdapterView.OnItemClickListener;
29import android.widget.AdapterView.OnItemLongClickListener;
30import android.widget.ArrayAdapter;
31import android.widget.EditText;
32import android.widget.ListView;
33import android.widget.ProgressBar;
34import android.widget.TextView;
35import android.widget.ImageView;
36import android.annotation.SuppressLint;
37import android.app.Activity;
38import android.app.AlertDialog;
39import android.content.Context;
40import android.content.DialogInterface;
41import android.content.DialogInterface.OnClickListener;
42import android.content.Intent;
43
44public class NewConversationActivity extends XmppActivity {
45
46 protected List<Contact> rosterContacts = new ArrayList<Contact>();
47 protected List<Contact> aggregatedContacts = new ArrayList<Contact>();
48 protected ListView contactsView;
49 protected ArrayAdapter<Contact> contactsAdapter;
50
51 protected EditText search;
52 protected String searchString = "";
53 private TextView contactsHeader;
54 private List<Account> accounts;
55
56 protected void updateAggregatedContacts() {
57
58 aggregatedContacts.clear();
59 for (Contact contact : rosterContacts) {
60 if (contact.match(searchString))
61 aggregatedContacts.add(contact);
62 }
63
64 Collections.sort(aggregatedContacts, new Comparator<Contact>() {
65
66 @SuppressLint("DefaultLocale")
67 @Override
68 public int compare(Contact lhs, Contact rhs) {
69 return lhs.getDisplayName().toLowerCase()
70 .compareTo(rhs.getDisplayName().toLowerCase());
71 }
72 });
73
74 if (aggregatedContacts.size() == 0) {
75
76 if (Validator.isValidJid(searchString)) {
77 String name = searchString.split("@")[0];
78 Contact newContact = new Contact(null, name, searchString, null);
79 newContact.flagAsNotInRoster();
80 aggregatedContacts.add(newContact);
81 contactsHeader.setText("Create new contact");
82 } else {
83 contactsHeader.setText("Contacts");
84 }
85 } else {
86 contactsHeader.setText("Contacts");
87 }
88
89 contactsAdapter.notifyDataSetChanged();
90 contactsView.setScrollX(0);
91 }
92
93 @Override
94 protected void onCreate(Bundle savedInstanceState) {
95
96 super.onCreate(savedInstanceState);
97
98 setContentView(R.layout.activity_new_conversation);
99
100 contactsHeader = (TextView) findViewById(R.id.contacts_header);
101
102 search = (EditText) findViewById(R.id.new_conversation_search);
103 search.addTextChangedListener(new TextWatcher() {
104
105 @Override
106 public void onTextChanged(CharSequence s, int start, int before,
107 int count) {
108 searchString = search.getText().toString();
109 updateAggregatedContacts();
110 }
111
112 @Override
113 public void afterTextChanged(Editable s) {
114 // TODO Auto-generated method stub
115
116 }
117
118 @Override
119 public void beforeTextChanged(CharSequence s, int start, int count,
120 int after) {
121 // TODO Auto-generated method stub
122
123 }
124 });
125
126 contactsView = (ListView) findViewById(R.id.contactList);
127 contactsAdapter = new ArrayAdapter<Contact>(getApplicationContext(),
128 R.layout.contact, aggregatedContacts) {
129 @Override
130 public View getView(int position, View view, ViewGroup parent) {
131 LayoutInflater inflater = (LayoutInflater) getSystemService(Context.LAYOUT_INFLATER_SERVICE);
132 Contact contact = getItem(position);
133 if (view == null) {
134 view = (View) inflater.inflate(R.layout.contact, null);
135 }
136
137 ((TextView) view.findViewById(R.id.contact_display_name))
138 .setText(getItem(position).getDisplayName());
139 TextView contactJid = (TextView) view
140 .findViewById(R.id.contact_jid);
141 contactJid.setText(contact.getJid());
142 ImageView imageView = (ImageView) view
143 .findViewById(R.id.contact_photo);
144 imageView.setImageBitmap(UIHelper.getContactPicture(contact,null,90,this.getContext()));
145 return view;
146 }
147 };
148 contactsView.setAdapter(contactsAdapter);
149 final Activity activity = this;
150 contactsView.setOnItemClickListener(new OnItemClickListener() {
151
152 @Override
153 public void onItemClick(AdapterView<?> arg0, final View view,
154 int pos, long arg3) {
155 final Contact clickedContact = aggregatedContacts.get(pos);
156
157 if ((clickedContact.getAccount()==null)&&(accounts.size()>1)) {
158 getAccountChooser(new OnClickListener() {
159
160 @Override
161 public void onClick(DialogInterface dialog, int which) {
162 clickedContact.setAccount(accounts.get(which));
163 showIsMucDialogIfNeeded(clickedContact);
164 }
165 }).show();
166 } else {
167 if (clickedContact.getAccount()==null) {
168 clickedContact.setAccount(accounts.get(0));
169 }
170 showIsMucDialogIfNeeded(clickedContact);
171 }
172 }
173 });
174 contactsView.setOnItemLongClickListener(new OnItemLongClickListener() {
175
176 @Override
177 public boolean onItemLongClick(AdapterView<?> arg0, View arg1,
178 int pos, long arg3) {
179 Intent intent = new Intent(activity,ContactDetailsActivity.class);
180 intent.setAction(ContactDetailsActivity.ACTION_VIEW_CONTACT);
181 intent.putExtra("uuid", aggregatedContacts.get(pos).getUuid());
182 startActivity(intent);
183 return true;
184 }
185 });
186 }
187
188 protected AlertDialog getAccountChooser(OnClickListener listener) {
189 String[] accountList = new String[accounts.size()];
190 for (int i = 0; i < accounts.size(); ++i) {
191 accountList[i] = accounts.get(i).getJid();
192 }
193
194 AlertDialog.Builder accountChooser = new AlertDialog.Builder(
195 this);
196 accountChooser.setTitle("Choose account");
197 accountChooser.setItems(accountList, listener);
198 return accountChooser.create();
199 }
200
201 public void showIsMucDialogIfNeeded(final Contact clickedContact) {
202 if (clickedContact.couldBeMuc()) {
203 AlertDialog.Builder dialog = new AlertDialog.Builder(this);
204 dialog.setTitle("Multi User Conference");
205 dialog.setMessage("Are you trying to join a conference?");
206 dialog.setPositiveButton("Yes", new OnClickListener() {
207
208 @Override
209 public void onClick(DialogInterface dialog, int which) {
210 startConversation(clickedContact, clickedContact.getAccount(),true);
211 }
212 });
213 dialog.setNegativeButton("No", new OnClickListener() {
214
215 @Override
216 public void onClick(DialogInterface dialog, int which) {
217 startConversation(clickedContact, clickedContact.getAccount(),false);
218 }
219 });
220 dialog.create().show();
221 } else {
222 startConversation(clickedContact, clickedContact.getAccount(),false);
223 }
224 }
225
226 public void startConversation(Contact contact, Account account, boolean muc) {
227 if (!contact.isInRoster()) {
228 xmppConnectionService.createContact(contact);
229 }
230 Conversation conversation = xmppConnectionService
231 .findOrCreateConversation(account, contact.getJid(), muc);
232
233 switchToConversation(conversation);
234 }
235
236 public void switchToConversation(Conversation conversation) {
237 Intent viewConversationIntent = new Intent(this,
238 ConversationActivity.class);
239 viewConversationIntent.setAction(Intent.ACTION_VIEW);
240 viewConversationIntent.putExtra(ConversationActivity.CONVERSATION,
241 conversation.getUuid());
242 viewConversationIntent.setType(ConversationActivity.VIEW_CONVERSATION);
243 viewConversationIntent.setFlags(viewConversationIntent.getFlags()
244 | Intent.FLAG_ACTIVITY_CLEAR_TOP);
245 startActivity(viewConversationIntent);
246 }
247
248 @Override
249 void onBackendConnected() {
250 this.accounts = xmppConnectionService.getAccounts();
251 if (Intent.ACTION_SENDTO.equals(getIntent().getAction())) {
252 getActionBar().setDisplayHomeAsUpEnabled(false);
253 getActionBar().setHomeButtonEnabled(false);
254 String jid;
255 try {
256 jid = URLDecoder.decode(getIntent().getData().getEncodedPath(),"UTF-8").split("/")[1];
257 } catch (UnsupportedEncodingException e) {
258 jid = null;
259 }
260 if (jid!=null) {
261 final String finalJid = jid;
262 if (this.accounts.size() > 1) {
263 getAccountChooser(new OnClickListener() {
264
265 @Override
266 public void onClick(DialogInterface dialog, int which) {
267 Conversation conversation = xmppConnectionService.findOrCreateConversation(accounts.get(which), finalJid, false);
268 switchToConversation(conversation);
269 }
270 }).show();
271 } else {
272 Conversation conversation = xmppConnectionService.findOrCreateConversation(this.accounts.get(0), jid, false);
273 switchToConversation(conversation);
274 }
275 }
276 }
277
278
279 if (xmppConnectionService.getConversationCount() == 0) {
280 getActionBar().setDisplayHomeAsUpEnabled(false);
281 getActionBar().setHomeButtonEnabled(false);
282 }
283 this.rosterContacts.clear();
284 for (int i = 0; i < accounts.size(); ++i) {
285 xmppConnectionService.getRoster(accounts.get(i),
286 new OnRosterFetchedListener() {
287
288 @Override
289 public void onRosterFetched(List<Contact> roster) {
290 rosterContacts.addAll(roster);
291 runOnUiThread(new Runnable() {
292
293 @Override
294 public void run() {
295 updateAggregatedContacts();
296 }
297 });
298
299 }
300 });
301 }
302 }
303
304 @Override
305 public boolean onCreateOptionsMenu(Menu menu) {
306 // Inflate the menu; this adds items to the action bar if it is present.
307 getMenuInflater().inflate(R.menu.newconversation, menu);
308 return true;
309 }
310
311 @Override
312 public boolean onOptionsItemSelected(MenuItem item) {
313 switch (item.getItemId()) {
314 case R.id.action_refresh_contacts:
315 refreshContacts();
316 break;
317 default:
318 break;
319 }
320 return super.onOptionsItemSelected(item);
321 }
322
323 private void refreshContacts() {
324 final ProgressBar progress = (ProgressBar) findViewById(R.id.progressBar1);
325 final EditText searchBar = (EditText) findViewById(R.id.new_conversation_search);
326 final TextView contactsHeader = (TextView) findViewById(R.id.contacts_header);
327 final ListView contactList = (ListView) findViewById(R.id.contactList);
328 searchBar.setVisibility(View.GONE);
329 contactsHeader.setVisibility(View.GONE);
330 contactList.setVisibility(View.GONE);
331 progress.setVisibility(View.VISIBLE);
332 this.accounts = xmppConnectionService.getAccounts();
333 this.rosterContacts.clear();
334 for (int i = 0; i < accounts.size(); ++i) {
335 if (accounts.get(i).getStatus() == Account.STATUS_ONLINE) {
336 xmppConnectionService.updateRoster(accounts.get(i),
337 new OnRosterFetchedListener() {
338
339 @Override
340 public void onRosterFetched(
341 final List<Contact> roster) {
342 runOnUiThread(new Runnable() {
343
344 @Override
345 public void run() {
346 rosterContacts.addAll(roster);
347 progress.setVisibility(View.GONE);
348 searchBar.setVisibility(View.VISIBLE);
349 contactList.setVisibility(View.VISIBLE);
350 contactList.setVisibility(View.VISIBLE);
351 updateAggregatedContacts();
352 }
353 });
354 }
355 });
356 }
357 }
358 }
359}