1package eu.siacs.conversations.ui;
2
3import java.util.ArrayList;
4import java.util.Collections;
5import java.util.List;
6
7import android.app.ActionBar;
8import android.app.ActionBar.Tab;
9import android.app.ActionBar.TabListener;
10import android.app.AlertDialog;
11import android.app.Fragment;
12import android.app.FragmentTransaction;
13import android.app.ListFragment;
14import android.content.Context;
15import android.graphics.Color;
16import android.os.Bundle;
17import android.support.v13.app.FragmentPagerAdapter;
18import android.support.v4.view.ViewPager;
19import android.view.ContextMenu;
20import android.view.ContextMenu.ContextMenuInfo;
21import android.view.LayoutInflater;
22import android.view.Menu;
23import android.view.MenuItem;
24import android.view.View;
25import android.view.ViewGroup;
26import android.widget.AdapterView;
27import android.widget.AdapterView.AdapterContextMenuInfo;
28import android.widget.AdapterView.OnItemClickListener;
29import android.widget.ArrayAdapter;
30import android.widget.AutoCompleteTextView;
31import android.widget.ImageView;
32import android.widget.ListView;
33import android.widget.SearchView;
34import android.widget.SearchView.OnQueryTextListener;
35import android.widget.Spinner;
36import android.widget.TextView;
37import eu.siacs.conversations.R;
38import eu.siacs.conversations.entities.Account;
39import eu.siacs.conversations.entities.Contact;
40import eu.siacs.conversations.entities.Conversation;
41import eu.siacs.conversations.entities.ListItem;
42import eu.siacs.conversations.utils.KnownHostsAdapter;
43import eu.siacs.conversations.utils.UIHelper;
44import eu.siacs.conversations.utils.Validator;
45
46public class StartConversation extends XmppActivity {
47
48 private Tab mContactsTab;
49 private Tab mConferencesTab;
50 private ViewPager mViewPager;
51 private SearchView mSearchView;
52
53 private MyListFragment mContactsListFragment = new MyListFragment();
54 private List<ListItem> contacts = new ArrayList<ListItem>();
55 private ArrayAdapter<ListItem> mContactsAdapter;
56
57 private MyListFragment mConferenceListFragment = new MyListFragment();
58 private List<ListItem> conferences = new ArrayList<ListItem>();
59 private ArrayAdapter<ListItem> mConferenceAdapter;
60
61 private List<String> mActivatedAccounts = new ArrayList<String>();
62 private List<String> mKnownHosts;
63
64 private TabListener mTabListener = new TabListener() {
65
66 @Override
67 public void onTabUnselected(Tab tab, FragmentTransaction ft) {
68 return;
69 }
70
71 @Override
72 public void onTabSelected(Tab tab, FragmentTransaction ft) {
73 mViewPager.setCurrentItem(tab.getPosition());
74 onTabChanged();
75 }
76
77 @Override
78 public void onTabReselected(Tab tab, FragmentTransaction ft) {
79 return;
80 }
81 };
82
83 private ViewPager.SimpleOnPageChangeListener mOnPageChangeListener = new ViewPager.SimpleOnPageChangeListener() {
84 @Override
85 public void onPageSelected(int position) {
86 getActionBar().setSelectedNavigationItem(position);
87 onTabChanged();
88 }
89 };
90 private OnQueryTextListener mOnQueryTextListener = new OnQueryTextListener() {
91
92 @Override
93 public boolean onQueryTextSubmit(String query) {
94 return true;
95 }
96
97 @Override
98 public boolean onQueryTextChange(String newText) {
99 filterContacts(newText);
100 return true;
101 }
102 };
103
104 @Override
105 public void onCreate(Bundle savedInstanceState) {
106 super.onCreate(savedInstanceState);
107 setContentView(R.layout.activity_start_conversation);
108 mViewPager = (ViewPager) findViewById(R.id.start_conversation_view_pager);
109 ActionBar actionBar = getActionBar();
110 actionBar.setNavigationMode(ActionBar.NAVIGATION_MODE_TABS);
111
112 mContactsTab = actionBar.newTab().setText(R.string.contacts)
113 .setTabListener(mTabListener);
114 mConferencesTab = actionBar.newTab().setText(R.string.conferences)
115 .setTabListener(mTabListener);
116 actionBar.addTab(mContactsTab);
117 actionBar.addTab(mConferencesTab);
118
119 mViewPager.setOnPageChangeListener(mOnPageChangeListener);
120 mViewPager.setAdapter(new FragmentPagerAdapter(getFragmentManager()) {
121
122 @Override
123 public int getCount() {
124 return 2;
125 }
126
127 @Override
128 public Fragment getItem(int position) {
129 if (position == 0) {
130 return mContactsListFragment;
131 } else {
132 return mConferenceListFragment;
133 }
134 }
135 });
136
137 mConferenceAdapter = new ListItemAdapter(conferences);
138 mConferenceListFragment.setListAdapter(mConferenceAdapter);
139
140 mContactsAdapter = new ListItemAdapter(contacts);
141 mContactsListFragment.setListAdapter(mContactsAdapter);
142 mContactsListFragment
143 .setOnListItemClickListener(new OnItemClickListener() {
144
145 @Override
146 public void onItemClick(AdapterView<?> arg0, View arg1,
147 int position, long arg3) {
148 openConversationForContact(position);
149 }
150 });
151
152 }
153
154 protected void openConversationForContact(int position) {
155 Contact contact = (Contact) contacts.get(position);
156 Conversation conversation = xmppConnectionService
157 .findOrCreateConversation(contact.getAccount(),
158 contact.getJid(), false);
159 switchToConversation(conversation, null, false);
160 }
161
162 protected void openDetailsForContact(int position) {
163 Contact contact = (Contact) contacts.get(position);
164 switchToContactDetails(contact);
165 }
166
167 protected void deleteContact(int position) {
168 Contact contact = (Contact) contacts.get(position);
169 xmppConnectionService.deleteContactOnServer(contact);
170 filterContacts(null);
171 }
172
173 protected void showCreateContactDialog() {
174 AlertDialog.Builder builder = new AlertDialog.Builder(this);
175 builder.setTitle(R.string.create_contact);
176 View dialogView = getLayoutInflater().inflate(R.layout.create_contact_dialog, null);
177 final Spinner spinner = (Spinner) dialogView.findViewById(R.id.account);
178 final AutoCompleteTextView jid = (AutoCompleteTextView) dialogView.findViewById(R.id.jid);
179 jid.setAdapter(new KnownHostsAdapter(this, android.R.layout.simple_list_item_1, mKnownHosts));
180 populateAccountSpinner(spinner);
181 builder.setView(dialogView);
182 builder.setNegativeButton(R.string.cancel, null);
183 builder.setPositiveButton(R.string.create, null);
184 final AlertDialog dialog = builder.create();
185 dialog.show();
186 dialog.getButton(AlertDialog.BUTTON_POSITIVE).setOnClickListener(new View.OnClickListener() {
187
188 @Override
189 public void onClick(View v) {
190 if (Validator.isValidJid(jid.getText().toString())) {
191 String accountJid = (String) spinner.getSelectedItem();
192 String contactJid = jid.getText().toString();
193 Account account = xmppConnectionService.findAccountByJid(accountJid);
194 Contact contact = account.getRoster().getContact(contactJid);
195 if (contact.showInRoster()) {
196 jid.setError(getString(R.string.contact_already_exists));
197 } else {
198 xmppConnectionService.createContact(contact);
199 switchToConversation(contact);
200 dialog.dismiss();
201 }
202 } else {
203 jid.setError(getString(R.string.invalid_jid));
204 }
205 }
206 });
207
208 }
209
210 protected void switchToConversation(Contact contact) {
211 Conversation conversation = xmppConnectionService.findOrCreateConversation(contact.getAccount(), contact.getJid(), false);
212 switchToConversation(conversation, null, false);
213 }
214
215 private void populateAccountSpinner(Spinner spinner) {
216 ArrayAdapter<String> adapter = new ArrayAdapter<String>(this, android.R.layout.simple_spinner_item, mActivatedAccounts);
217 adapter.setDropDownViewResource(android.R.layout.simple_spinner_dropdown_item);
218 spinner.setAdapter(adapter);
219 }
220
221 @Override
222 public boolean onCreateOptionsMenu(Menu menu) {
223 getMenuInflater().inflate(R.menu.start_conversation, menu);
224 MenuItem menuCreateContact = (MenuItem) menu
225 .findItem(R.id.action_create_contact);
226 MenuItem menuCreateConference = (MenuItem) menu
227 .findItem(R.id.action_create_conference);
228 MenuItem menuSearch = (MenuItem) menu.findItem(R.id.action_search);
229 if (getActionBar().getSelectedNavigationIndex() == 0) {
230 menuCreateConference.setVisible(false);
231 } else {
232 menuCreateContact.setVisible(false);
233 }
234 mSearchView = (SearchView) menuSearch.getActionView();
235 int id = mSearchView.getContext().getResources()
236 .getIdentifier("android:id/search_src_text", null, null);
237 TextView textView = (TextView) mSearchView.findViewById(id);
238 textView.setTextColor(Color.WHITE);
239 mSearchView.setOnQueryTextListener(this.mOnQueryTextListener);
240 return true;
241 }
242
243 @Override
244 public boolean onOptionsItemSelected(MenuItem item) {
245 switch (item.getItemId()) {
246 case R.id.action_create_contact:
247 showCreateContactDialog();
248 break;
249 }
250 return super.onOptionsItemSelected(item);
251 }
252
253 @Override
254 void onBackendConnected() {
255 filterContacts(null);
256 this.mActivatedAccounts.clear();
257 for (Account account : xmppConnectionService.getAccounts()) {
258 if (account.getStatus() != Account.STATUS_DISABLED) {
259 this.mActivatedAccounts.add(account.getJid());
260 }
261 }
262 this.mKnownHosts = xmppConnectionService.getKnownHosts();
263 }
264
265 protected void filterContacts(String needle) {
266 this.contacts.clear();
267 for (Account account : xmppConnectionService.getAccounts()) {
268 if (account.getStatus() != Account.STATUS_DISABLED) {
269 for (Contact contact : account.getRoster().getContacts()) {
270 if (contact.showInRoster() && contact.match(needle)) {
271 this.contacts.add(contact);
272 }
273 }
274 }
275 }
276 Collections.sort(this.contacts);
277 mContactsAdapter.notifyDataSetChanged();
278 }
279
280 private void onTabChanged() {
281 invalidateOptionsMenu();
282 }
283
284 private class ListItemAdapter extends ArrayAdapter<ListItem> {
285
286 public ListItemAdapter(List<ListItem> objects) {
287 super(getApplicationContext(), 0, objects);
288 }
289
290 @Override
291 public View getView(int position, View view, ViewGroup parent) {
292 LayoutInflater inflater = (LayoutInflater) getSystemService(Context.LAYOUT_INFLATER_SERVICE);
293 ListItem item = getItem(position);
294 if (view == null) {
295 view = (View) inflater.inflate(R.layout.contact, null);
296 }
297 TextView name = (TextView) view
298 .findViewById(R.id.contact_display_name);
299 TextView jid = (TextView) view.findViewById(R.id.contact_jid);
300 ImageView picture = (ImageView) view
301 .findViewById(R.id.contact_photo);
302
303 jid.setText(item.getJid());
304 name.setText(item.getDisplayName());
305 picture.setImageBitmap(UIHelper.getContactPicture(item, 48,
306 this.getContext(), false));
307 return view;
308 }
309
310 }
311
312 public static class MyListFragment extends ListFragment {
313 private AdapterView.OnItemClickListener mOnItemClickListener;
314 private int mContextPosition = -1;
315
316 @Override
317 public void onListItemClick(ListView l, View v, int position, long id) {
318 if (mOnItemClickListener != null) {
319 mOnItemClickListener.onItemClick(l, v, position, id);
320 }
321 }
322
323 public void setOnListItemClickListener(AdapterView.OnItemClickListener l) {
324 this.mOnItemClickListener = l;
325 }
326
327 @Override
328 public void onViewCreated(View view, Bundle savedInstanceState) {
329 super.onViewCreated(view, savedInstanceState);
330 registerForContextMenu(getListView());
331 }
332
333 @Override
334 public void onCreateContextMenu(ContextMenu menu, View v,
335 ContextMenuInfo menuInfo) {
336 super.onCreateContextMenu(menu, v, menuInfo);
337 getActivity().getMenuInflater().inflate(R.menu.contact_context,
338 menu);
339 AdapterView.AdapterContextMenuInfo acmi = (AdapterContextMenuInfo) menuInfo;
340 this.mContextPosition = acmi.position;
341 }
342
343 @Override
344 public boolean onContextItemSelected(MenuItem item) {
345 StartConversation activity = (StartConversation) getActivity();
346 switch(item.getItemId()) {
347 case R.id.context_start_conversation:
348 activity.openConversationForContact(mContextPosition);
349 break;
350 case R.id.context_contact_details:
351 activity.openDetailsForContact(mContextPosition);
352 break;
353 case R.id.context_delete_contact:
354 activity.deleteContact(mContextPosition);
355 break;
356 }
357 return true;
358 }
359 }
360}