Fix the look of tabbed multi-contact selector.
1) Updated to ActionBar style. 2) Split out into fragments. 3) Switch to cursor loaders.
@ -39,6 +39,11 @@
|
||||
android:windowSoftInputMode="stateVisible"
|
||||
android:configChanges="touchscreen|keyboard|keyboardHidden|orientation|screenLayout"/>
|
||||
|
||||
<activity android:name=".ContactSelectionActivity"
|
||||
android:label="Select Contacts"
|
||||
android:configChanges="touchscreen|keyboard|keyboardHidden|orientation|screenLayout"/>
|
||||
|
||||
|
||||
<activity android:name=".AutoInitiateActivity" android:theme="@android:style/Theme.Dialog" android:label="TextSecure Messaging Detected" android:configChanges="touchscreen|keyboard|keyboardHidden|orientation|screenLayout"></activity>
|
||||
<activity android:name=".ApplicationPreferencesActivity" android:configChanges="touchscreen|keyboard|keyboardHidden|orientation|screenLayout"></activity>
|
||||
<activity android:name=".PassphraseCreateActivity" android:theme="@android:style/Theme.Dialog" android:label="Create Passphrase" android:launchMode="singleInstance" android:configChanges="touchscreen|keyboard|keyboardHidden|orientation|screenLayout"></activity>
|
||||
@ -51,11 +56,6 @@
|
||||
<activity android:name=".ViewIdentityActivity" android:theme="@android:style/Theme.Dialog" android:label="Public Identity Key" android:configChanges="touchscreen|keyboard|keyboardHidden|orientation|screenLayout"></activity>
|
||||
<activity android:name=".SaveIdentityActivity" android:theme="@android:style/Theme.Dialog" android:label="Save Identity" android:configChanges="touchscreen|keyboard|keyboardHidden|orientation|screenLayout"></activity>
|
||||
<activity android:name=".ReviewIdentitiesActivity" android:theme="@android:style/Theme.Dialog" android:label="Manage Identity Keys (Long click)" android:configChanges="touchscreen|keyboard|keyboardHidden|orientation|screenLayout"></activity>
|
||||
<activity android:name=".ContactSelectionActivity" android:label="Contact Selection" android:configChanges="touchscreen|keyboard|keyboardHidden|orientation|screenLayout"></activity>
|
||||
<activity android:name=".ContactSelectionListActivity" android:label="Contact Selection" android:configChanges="touchscreen|keyboard|keyboardHidden|orientation|screenLayout"></activity>
|
||||
<activity android:name=".GroupSelectionListActivity" android:label="Group Selection" android:configChanges="touchscreen|keyboard|keyboardHidden|orientation|screenLayout"></activity>
|
||||
<activity android:name=".ContactSelectionRecentActivity" android:label="Recent Calls Selection" android:configChanges="touchscreen|keyboard|keyboardHidden|orientation|screenLayout"></activity>
|
||||
|
||||
|
||||
<service android:enabled="true" android:name=".service.KeyCachingService"></service>
|
||||
<service android:enabled="true" android:name=".service.SendReceiveService"></service>
|
||||
|
BIN
res/drawable-hdpi/hairline_left.9.png
Normal file
After Width: | Height: | Size: 1.1 KiB |
BIN
res/drawable-hdpi/hairline_right.9.png
Normal file
After Width: | Height: | Size: 1.1 KiB |
BIN
res/drawable-hdpi/ic_menu_done_holo_dark.png
Normal file
After Width: | Height: | Size: 1.0 KiB |
BIN
res/drawable-hdpi/ic_tab_contacts.png
Normal file
After Width: | Height: | Size: 1.5 KiB |
BIN
res/drawable-hdpi/ic_tab_groups.png
Normal file
After Width: | Height: | Size: 2.1 KiB |
BIN
res/drawable-hdpi/ic_tab_recent.png
Normal file
After Width: | Height: | Size: 1.8 KiB |
BIN
res/drawable-mdpi/hairline_left.9.png
Normal file
After Width: | Height: | Size: 1.1 KiB |
BIN
res/drawable-mdpi/hairline_right.9.png
Normal file
After Width: | Height: | Size: 1.1 KiB |
BIN
res/drawable-mdpi/ic_menu_done_holo_dark.png
Normal file
After Width: | Height: | Size: 694 B |
BIN
res/drawable-mdpi/ic_tab_contacts.png
Normal file
After Width: | Height: | Size: 1.0 KiB |
BIN
res/drawable-mdpi/ic_tab_groups.png
Normal file
After Width: | Height: | Size: 1.3 KiB |
BIN
res/drawable-mdpi/ic_tab_recent.png
Normal file
After Width: | Height: | Size: 1.1 KiB |
BIN
res/drawable-xhdpi/hairline_left.9.png
Normal file
After Width: | Height: | Size: 1.1 KiB |
BIN
res/drawable-xhdpi/hairline_right.9.png
Normal file
After Width: | Height: | Size: 1.1 KiB |
BIN
res/drawable-xhdpi/ic_menu_done_holo_dark.png
Normal file
After Width: | Height: | Size: 1.3 KiB |
BIN
res/drawable-xhdpi/ic_tab_contacts.png
Normal file
After Width: | Height: | Size: 2.0 KiB |
BIN
res/drawable-xhdpi/ic_tab_groups.png
Normal file
After Width: | Height: | Size: 3.0 KiB |
BIN
res/drawable-xhdpi/ic_tab_recent.png
Normal file
After Width: | Height: | Size: 2.7 KiB |
@ -1,42 +1,12 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<!-- Copyright (C) 2006 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.
|
||||
-->
|
||||
|
||||
<TabHost xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
android:id="@android:id/tabhost"
|
||||
<LinearLayout android:layout_gravity="center"
|
||||
android:layout_height="fill_parent"
|
||||
android:layout_width="fill_parent"
|
||||
android:layout_height="fill_parent">
|
||||
|
||||
<LinearLayout
|
||||
android:orientation="vertical"
|
||||
android:layout_width="fill_parent"
|
||||
android:layout_height="fill_parent">
|
||||
xmlns:android="http://schemas.android.com/apk/res/android">
|
||||
|
||||
<TabWidget android:id="@android:id/tabs"
|
||||
android:layout_width="fill_parent"
|
||||
android:layout_height="68dip"
|
||||
android:paddingLeft="1dip"
|
||||
android:paddingRight="1dip"
|
||||
android:paddingTop="4dip"
|
||||
/>
|
||||
|
||||
<FrameLayout android:id="@android:id/tabcontent"
|
||||
android:layout_width="fill_parent"
|
||||
android:layout_height="0dip"
|
||||
android:layout_weight="1"
|
||||
/>
|
||||
</LinearLayout>
|
||||
</TabHost>
|
||||
<LinearLayout android:id="@+id/fragment_container"
|
||||
android:layout_height="match_parent"
|
||||
android:layout_width="match_parent"/>
|
||||
|
||||
</LinearLayout>
|
9
res/menu/contact_selection.xml
Normal file
@ -0,0 +1,9 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<menu xmlns:android="http://schemas.android.com/apk/res/android">
|
||||
<item android:title="Finished"
|
||||
android:id="@+id/menu_selection_finished"
|
||||
android:icon="@drawable/ic_menu_done_holo_dark"
|
||||
android:showAsAction="ifRoom"
|
||||
/>
|
||||
|
||||
</menu>
|
8
res/menu/contact_selection_list.xml
Normal file
@ -0,0 +1,8 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<menu xmlns:android="http://schemas.android.com/apk/res/android">
|
||||
<item android:title="Select All"
|
||||
android:id="@+id/menu_select_all" />
|
||||
|
||||
<item android:title="Unselect All"
|
||||
android:id="@+id/menu_unselect_all" />
|
||||
</menu>
|
@ -16,13 +16,22 @@
|
||||
*/
|
||||
package org.thoughtcrime.securesms;
|
||||
|
||||
import org.thoughtcrime.securesms.service.KeyCachingService;
|
||||
|
||||
import android.app.TabActivity;
|
||||
import android.content.Intent;
|
||||
import android.os.Bundle;
|
||||
import android.view.Window;
|
||||
import android.widget.TabHost;
|
||||
import android.support.v4.app.Fragment;
|
||||
import android.support.v4.app.FragmentManager;
|
||||
import android.support.v4.app.FragmentTransaction;
|
||||
|
||||
import com.actionbarsherlock.app.ActionBar;
|
||||
import com.actionbarsherlock.app.ActionBar.Tab;
|
||||
import com.actionbarsherlock.app.ActionBar.TabListener;
|
||||
import com.actionbarsherlock.app.SherlockFragmentActivity;
|
||||
import com.actionbarsherlock.view.Menu;
|
||||
import com.actionbarsherlock.view.MenuInflater;
|
||||
import com.actionbarsherlock.view.MenuItem;
|
||||
|
||||
import org.thoughtcrime.securesms.recipients.Recipients;
|
||||
import org.thoughtcrime.securesms.service.KeyCachingService;
|
||||
|
||||
/**
|
||||
* Activity container for selecting a list of contacts. Provides a tab frame for
|
||||
@ -32,20 +41,23 @@ import android.widget.TabHost;
|
||||
* @author Moxie Marlinspike
|
||||
*
|
||||
*/
|
||||
public class ContactSelectionActivity extends SherlockFragmentActivity {
|
||||
|
||||
public class ContactSelectionActivity extends TabActivity implements TabHost.OnTabChangeListener {
|
||||
private ContactSelectionListFragment contactsFragment;
|
||||
private ContactSelectionGroupsFragment groupsFragment;
|
||||
private ContactSelectionRecentFragment recentFragment;
|
||||
|
||||
private TabHost tabHost;
|
||||
private Recipients recipients;
|
||||
|
||||
@Override
|
||||
protected void onCreate(Bundle icicle) {
|
||||
super.onCreate(icicle);
|
||||
|
||||
requestWindowFeature(Window.FEATURE_NO_TITLE);
|
||||
setContentView(R.layout.contact_selection_activity);
|
||||
ActionBar actionBar = this.getSupportActionBar();
|
||||
actionBar.setNavigationMode(ActionBar.NAVIGATION_MODE_TABS);
|
||||
actionBar.setDisplayHomeAsUpEnabled(true);
|
||||
|
||||
tabHost = getTabHost();
|
||||
tabHost.setOnTabChangedListener(this);
|
||||
setContentView(R.layout.contact_selection_activity);
|
||||
|
||||
setupContactsTab();
|
||||
setupGroupsTab();
|
||||
@ -65,10 +77,90 @@ public class ContactSelectionActivity extends TabActivity implements TabHost.OnT
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean onSearchRequested() {
|
||||
public boolean onCreateOptionsMenu(Menu menu) {
|
||||
MenuInflater inflater = this.getSupportMenuInflater();
|
||||
inflater.inflate(R.menu.contact_selection, menu);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean onOptionsItemSelected(MenuItem item) {
|
||||
switch (item.getItemId()) {
|
||||
case R.id.menu_selection_finished:
|
||||
case android.R.id.home:
|
||||
handleSelectionFinished(); return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
private void handleSelectionFinished() {
|
||||
recipients = contactsFragment.getSelectedContacts();
|
||||
recipients.append(recentFragment.getSelectedContacts());
|
||||
recipients.append(groupsFragment.getSelectedContacts());
|
||||
|
||||
Intent resultIntent = getIntent();
|
||||
resultIntent.putExtra("recipients", this.recipients);
|
||||
|
||||
setResult(RESULT_OK, resultIntent);
|
||||
|
||||
finish();
|
||||
}
|
||||
|
||||
private ActionBar.Tab constructTab(final Fragment fragment) {
|
||||
ActionBar actionBar = this.getSupportActionBar();
|
||||
ActionBar.Tab tab = actionBar.newTab();
|
||||
|
||||
tab.setTabListener(new TabListener(){
|
||||
@Override
|
||||
public void onTabSelected(Tab tab, FragmentTransaction ignore) {
|
||||
FragmentManager manager = ContactSelectionActivity.this.getSupportFragmentManager();
|
||||
FragmentTransaction ft = manager.beginTransaction();
|
||||
|
||||
ft.add(R.id.fragment_container, fragment);
|
||||
ft.commit();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onTabUnselected(Tab tab, FragmentTransaction ignore) {
|
||||
FragmentManager manager = ContactSelectionActivity.this.getSupportFragmentManager();
|
||||
FragmentTransaction ft = manager.beginTransaction();
|
||||
ft.remove(fragment);
|
||||
ft.commit();
|
||||
}
|
||||
@Override
|
||||
public void onTabReselected(Tab tab, FragmentTransaction ft) {}
|
||||
});
|
||||
|
||||
return tab;
|
||||
}
|
||||
|
||||
private void setupContactsTab() {
|
||||
contactsFragment = (ContactSelectionListFragment)Fragment.instantiate(this,
|
||||
ContactSelectionListFragment.class.getName());
|
||||
ActionBar.Tab contactsTab = constructTab(contactsFragment);
|
||||
contactsTab.setIcon(R.drawable.ic_tab_contacts);
|
||||
this.getSupportActionBar().addTab(contactsTab);
|
||||
}
|
||||
|
||||
private void setupGroupsTab() {
|
||||
groupsFragment = (ContactSelectionGroupsFragment)Fragment.instantiate(this,
|
||||
ContactSelectionGroupsFragment.class.getName());
|
||||
ActionBar.Tab groupsTab = constructTab(groupsFragment);
|
||||
groupsTab.setIcon(R.drawable.ic_tab_groups);
|
||||
this.getSupportActionBar().addTab(groupsTab);
|
||||
}
|
||||
|
||||
private void setupRecentTab() {
|
||||
recentFragment = (ContactSelectionRecentFragment)Fragment.instantiate(this,
|
||||
ContactSelectionRecentFragment.class.getName());
|
||||
|
||||
ActionBar.Tab recentTab = constructTab(recentFragment);
|
||||
recentTab.setIcon(R.drawable.ic_tab_recent);
|
||||
this.getSupportActionBar().addTab(recentTab);
|
||||
}
|
||||
|
||||
private void registerPassphraseActivityStarted() {
|
||||
Intent intent = new Intent(this, KeyCachingService.class);
|
||||
intent.setAction(KeyCachingService.ACTIVITY_START_EVENT);
|
||||
@ -81,32 +173,6 @@ public class ContactSelectionActivity extends TabActivity implements TabHost.OnT
|
||||
startService(intent);
|
||||
}
|
||||
|
||||
private void setupGroupsTab() {
|
||||
Intent intent = new Intent(this, GroupSelectionListActivity.class);
|
||||
|
||||
tabHost.addTab(tabHost.newTabSpec("groups")
|
||||
.setIndicator("Groups", getResources().getDrawable(android.R.drawable.ic_menu_share))
|
||||
.setContent(intent));
|
||||
}
|
||||
|
||||
private void setupRecentTab() {
|
||||
Intent intent = new Intent(this, ContactSelectionRecentActivity.class);
|
||||
|
||||
tabHost.addTab(tabHost.newTabSpec("recent")
|
||||
.setIndicator("Recent", getResources().getDrawable(android.R.drawable.ic_menu_call))
|
||||
.setContent(intent));
|
||||
}
|
||||
|
||||
private void setupContactsTab() {
|
||||
Intent intent = new Intent(this, ContactSelectionListActivity.class);
|
||||
|
||||
tabHost.addTab(tabHost.newTabSpec("contacts")
|
||||
.setIndicator("Contacts", getResources().getDrawable(android.R.drawable.ic_menu_agenda))
|
||||
.setContent(intent));
|
||||
}
|
||||
|
||||
public void onTabChanged(String tabId) {
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
@ -0,0 +1,231 @@
|
||||
/**
|
||||
* Copyright (C) 2011 Whisper Systems
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
package org.thoughtcrime.securesms;
|
||||
|
||||
import android.content.Context;
|
||||
import android.database.Cursor;
|
||||
import android.os.Bundle;
|
||||
import android.support.v4.app.LoaderManager;
|
||||
import android.support.v4.content.Loader;
|
||||
import android.util.Log;
|
||||
import android.view.LayoutInflater;
|
||||
import android.view.View;
|
||||
import android.view.ViewGroup;
|
||||
import android.widget.CheckedTextView;
|
||||
import android.widget.CursorAdapter;
|
||||
import android.widget.LinearLayout;
|
||||
import android.widget.ListView;
|
||||
|
||||
import com.actionbarsherlock.app.SherlockListFragment;
|
||||
|
||||
import org.thoughtcrime.securesms.contacts.ContactAccessor;
|
||||
import org.thoughtcrime.securesms.contacts.ContactAccessor.ContactData;
|
||||
import org.thoughtcrime.securesms.contacts.ContactAccessor.GroupData;
|
||||
import org.thoughtcrime.securesms.contacts.ContactAccessor.NumberData;
|
||||
import org.thoughtcrime.securesms.recipients.Recipient;
|
||||
import org.thoughtcrime.securesms.recipients.Recipients;
|
||||
|
||||
import java.util.HashMap;
|
||||
import java.util.LinkedList;
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* An activity for selecting a list of "contact groups." Displayed
|
||||
* by ContactSelectionActivity in a tabbed frame, and ultimately called
|
||||
* by ComposeMessageActivity for selecting a list of recipients.
|
||||
*
|
||||
* @author Moxie Marlinspike
|
||||
*
|
||||
*/
|
||||
public class ContactSelectionGroupsFragment extends SherlockListFragment
|
||||
implements LoaderManager.LoaderCallbacks<Cursor>
|
||||
{
|
||||
|
||||
private final HashMap<Long, GroupData> selectedGroups = new HashMap<Long, GroupData>();
|
||||
|
||||
@Override
|
||||
public void onActivityCreated(Bundle icicle) {
|
||||
super.onActivityCreated(icicle);
|
||||
|
||||
initializeResources();
|
||||
initializeCursor();
|
||||
}
|
||||
|
||||
@Override
|
||||
public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
|
||||
return inflater.inflate(R.layout.contact_selection_group_activity, container, false);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onListItemClick(ListView l, View v, int position, long id) {
|
||||
((GroupItemView)v).selected();
|
||||
}
|
||||
|
||||
private void initializeCursor() {
|
||||
setListAdapter(new GroupSelectionListAdapter(getActivity(), null));
|
||||
this.getLoaderManager().initLoader(0, null, this);
|
||||
}
|
||||
|
||||
private void initializeResources() {
|
||||
this.getListView().setFocusable(true);
|
||||
}
|
||||
|
||||
public Recipients getSelectedContacts() {
|
||||
List<Recipient> recipientList = new LinkedList<Recipient>();
|
||||
|
||||
for (GroupData groupData : selectedGroups.values()) {
|
||||
List<ContactData> contactDataList = ContactAccessor.getInstance()
|
||||
.getGroupMembership(getActivity(), groupData.id);
|
||||
|
||||
Log.w("GroupSelectionListActivity", "Got contacts in group: " + contactDataList.size());
|
||||
|
||||
for (ContactData contactData : contactDataList) {
|
||||
for (NumberData numberData : contactData.numbers) {
|
||||
recipientList.add(new Recipient(contactData.name, numberData.number, null));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return new Recipients(recipientList);
|
||||
}
|
||||
|
||||
private void addGroup(GroupData groupData) {
|
||||
selectedGroups.put(groupData.id, groupData);
|
||||
}
|
||||
|
||||
private void removeGroup(GroupData groupData) {
|
||||
selectedGroups.remove(groupData.id);
|
||||
}
|
||||
|
||||
private class GroupSelectionListAdapter extends CursorAdapter {
|
||||
|
||||
public GroupSelectionListAdapter(Context context, Cursor cursor) {
|
||||
super(context, cursor);
|
||||
}
|
||||
|
||||
@Override
|
||||
public View newView(Context context, Cursor cursor, ViewGroup parent) {
|
||||
GroupItemView view = new GroupItemView(context);
|
||||
bindView(view, context, cursor);
|
||||
return view;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void bindView(View view, Context context, Cursor cursor) {
|
||||
GroupData groupData = ContactAccessor.getInstance().getGroupData(getActivity(), cursor);
|
||||
((GroupItemView)view).set(groupData);
|
||||
}
|
||||
}
|
||||
|
||||
private class GroupItemView extends LinearLayout {
|
||||
private GroupData groupData;
|
||||
private CheckedTextView name;
|
||||
|
||||
public GroupItemView(Context context) {
|
||||
super(context);
|
||||
|
||||
LayoutInflater li = (LayoutInflater)context.getSystemService(Context.LAYOUT_INFLATER_SERVICE);
|
||||
li.inflate(R.layout.contact_selection_group_item, this, true);
|
||||
|
||||
this.name = (CheckedTextView)findViewById(R.id.name);
|
||||
}
|
||||
|
||||
public void selected() {
|
||||
name.toggle();
|
||||
|
||||
if (name.isChecked()) {
|
||||
addGroup(groupData);
|
||||
} else {
|
||||
removeGroup(groupData);
|
||||
}
|
||||
}
|
||||
|
||||
public void set(GroupData groupData) {
|
||||
this.groupData = groupData;
|
||||
|
||||
if (selectedGroups.containsKey(groupData.id))
|
||||
this.name.setChecked(true);
|
||||
else
|
||||
this.name.setChecked(false);
|
||||
|
||||
this.name.setText(groupData.name);
|
||||
}
|
||||
}
|
||||
|
||||
// private class GroupAggregationHandler extends Handler implements Runnable {
|
||||
// private List<Recipient> recipientList = new LinkedList<Recipient>();
|
||||
// private ProgressDialog progressDialog;
|
||||
// private final Context context;
|
||||
//
|
||||
// public GroupAggregationHandler(Context context) {
|
||||
// this.context = context;
|
||||
// }
|
||||
//
|
||||
// public void run() {
|
||||
// recipientList.clear();
|
||||
//
|
||||
// for (GroupData groupData : selectedGroups.values()) {
|
||||
// List<ContactData> contactDataList = ContactAccessor.getInstance()
|
||||
// .getGroupMembership(getActivity(), groupData.id);
|
||||
//
|
||||
// Log.w("GroupSelectionListActivity", "Got contacts in group: " + contactDataList.size());
|
||||
//
|
||||
// for (ContactData contactData : contactDataList) {
|
||||
// for (NumberData numberData : contactData.numbers) {
|
||||
// recipientList.add(new Recipient(contactData.name, numberData.number, null));
|
||||
// }
|
||||
// }
|
||||
// }
|
||||
//
|
||||
// this.obtainMessage().sendToTarget();
|
||||
// }
|
||||
//
|
||||
// public void aggregateContacts() {
|
||||
// progressDialog = new ProgressDialog(context);
|
||||
// progressDialog.setTitle("Aggregating Contacts");
|
||||
// progressDialog.setMessage("Aggregating group contacts...");
|
||||
// progressDialog.setCancelable(false);
|
||||
// progressDialog.setIndeterminate(true);
|
||||
// progressDialog.setProgressStyle(ProgressDialog.STYLE_SPINNER);
|
||||
// progressDialog.show();
|
||||
// Log.w("GroupSelectionListActivity", "Showing group spinner...");
|
||||
// new Thread(this).start();
|
||||
// }
|
||||
//
|
||||
// @Override
|
||||
// public void handleMessage(Message message) {
|
||||
// progressDialog.dismiss();
|
||||
//
|
||||
// listener.groupAggregationComplete(new Recipients(recipientList));
|
||||
// }
|
||||
// }
|
||||
|
||||
@Override
|
||||
public Loader<Cursor> onCreateLoader(int arg0, Bundle arg1) {
|
||||
return ContactAccessor.getInstance().getCursorLoaderForContactGroups(getActivity());
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onLoadFinished(Loader<Cursor> arg0, Cursor cursor) {
|
||||
((CursorAdapter)getListAdapter()).changeCursor(cursor);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onLoaderReset(Loader<Cursor> arg0) {
|
||||
((CursorAdapter)getListAdapter()).changeCursor(null);
|
||||
}
|
||||
}
|
@ -17,28 +17,15 @@
|
||||
package org.thoughtcrime.securesms;
|
||||
|
||||
|
||||
import java.util.HashMap;
|
||||
import java.util.LinkedList;
|
||||
import java.util.List;
|
||||
|
||||
import org.thoughtcrime.securesms.contacts.ContactAccessor;
|
||||
import org.thoughtcrime.securesms.contacts.ContactAccessor.ContactData;
|
||||
import org.thoughtcrime.securesms.contacts.ContactAccessor.NumberData;
|
||||
import org.thoughtcrime.securesms.recipients.Recipient;
|
||||
import org.thoughtcrime.securesms.recipients.Recipients;
|
||||
|
||||
import android.app.AlertDialog;
|
||||
import android.app.ListActivity;
|
||||
import android.content.Context;
|
||||
import android.content.DialogInterface;
|
||||
import android.content.Intent;
|
||||
import android.database.Cursor;
|
||||
import android.os.Bundle;
|
||||
import android.support.v4.app.LoaderManager;
|
||||
import android.support.v4.content.Loader;
|
||||
import android.util.Log;
|
||||
import android.view.KeyEvent;
|
||||
import android.view.LayoutInflater;
|
||||
import android.view.Menu;
|
||||
import android.view.MenuItem;
|
||||
import android.view.View;
|
||||
import android.view.ViewGroup;
|
||||
import android.widget.CheckedTextView;
|
||||
@ -47,6 +34,21 @@ import android.widget.ListView;
|
||||
import android.widget.RelativeLayout;
|
||||
import android.widget.TextView;
|
||||
|
||||
import com.actionbarsherlock.app.SherlockListFragment;
|
||||
import com.actionbarsherlock.view.Menu;
|
||||
import com.actionbarsherlock.view.MenuInflater;
|
||||
import com.actionbarsherlock.view.MenuItem;
|
||||
|
||||
import org.thoughtcrime.securesms.contacts.ContactAccessor;
|
||||
import org.thoughtcrime.securesms.contacts.ContactAccessor.ContactData;
|
||||
import org.thoughtcrime.securesms.contacts.ContactAccessor.NumberData;
|
||||
import org.thoughtcrime.securesms.recipients.Recipient;
|
||||
import org.thoughtcrime.securesms.recipients.Recipients;
|
||||
|
||||
import java.util.HashMap;
|
||||
import java.util.LinkedList;
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* Activity for selecting a list of contacts. Displayed inside
|
||||
* a ContactSelectionActivity tab frame, and ultimately called by
|
||||
@ -56,75 +58,72 @@ import android.widget.TextView;
|
||||
*
|
||||
*/
|
||||
|
||||
public class ContactSelectionListActivity extends ListActivity {
|
||||
public class ContactSelectionListFragment extends SherlockListFragment
|
||||
implements LoaderManager.LoaderCallbacks<Cursor>
|
||||
{
|
||||
|
||||
private final HashMap<Long, ContactData> selectedContacts = new HashMap<Long, ContactData>();
|
||||
|
||||
private static final int MENU_OPTION_EXIT = 1;
|
||||
private static final int MENU_OPTION_SELECT_ALL = 2;
|
||||
private static final int MENU_OPTION_UNSELECT_ALL = 3;
|
||||
|
||||
@Override
|
||||
protected void onCreate(Bundle icicle) {
|
||||
public void onActivityCreated(Bundle icicle) {
|
||||
super.onCreate(icicle);
|
||||
|
||||
setContentView(R.layout.contact_selection_list_activity);
|
||||
initializeResources();
|
||||
displayContacts();
|
||||
initializeCursor();
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean onPrepareOptionsMenu(Menu menu) {
|
||||
super.onPrepareOptionsMenu(menu);
|
||||
menu.clear();
|
||||
public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
|
||||
return inflater.inflate(R.layout.contact_selection_list_activity, container, false);
|
||||
}
|
||||
|
||||
menu.add(0, MENU_OPTION_EXIT, Menu.NONE, "Finished!").setIcon(android.R.drawable.ic_menu_set_as);
|
||||
menu.add(0, MENU_OPTION_SELECT_ALL, Menu.NONE, "Select all").setIcon(android.R.drawable.ic_menu_add);
|
||||
menu.add(0, MENU_OPTION_UNSELECT_ALL, Menu.NONE, "Unselect all").setIcon(android.R.drawable.ic_menu_revert);
|
||||
|
||||
return true;
|
||||
@Override
|
||||
public void onCreateOptionsMenu(Menu menu, MenuInflater inflater) {
|
||||
inflater.inflate(R.menu.contact_selection_list, menu);
|
||||
super.onCreateOptionsMenu(menu, inflater);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean onOptionsItemSelected(MenuItem item) {
|
||||
super.onOptionsItemSelected(item);
|
||||
|
||||
switch (item.getItemId()) {
|
||||
case MENU_OPTION_EXIT: saveAndExit(); return true;
|
||||
case MENU_OPTION_SELECT_ALL: selectAll(); return true;
|
||||
case MENU_OPTION_UNSELECT_ALL: unselectAll(); return true;
|
||||
case R.id.menu_select_all: handleSelectAll(); return true;
|
||||
case R.id.menu_unselect_all: handleUnselectAll(); return true;
|
||||
}
|
||||
|
||||
super.onOptionsItemSelected(item);
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public boolean onKeyDown(int keyCode, KeyEvent event) {
|
||||
if (keyCode == KeyEvent.KEYCODE_BACK && event.getRepeatCount() == 0) {
|
||||
saveAndExit();
|
||||
return true;
|
||||
public Recipients getSelectedContacts() {
|
||||
List<Recipient> recipientList = new LinkedList<Recipient>();
|
||||
|
||||
for (ContactData contactData : selectedContacts.values()) {
|
||||
for (NumberData numberData : contactData.numbers) {
|
||||
recipientList.add(new Recipient(contactData.name, numberData.number, null));
|
||||
}
|
||||
}
|
||||
|
||||
return super.onKeyDown(keyCode, event);
|
||||
return new Recipients(recipientList);
|
||||
}
|
||||
|
||||
private void unselectAll() {
|
||||
|
||||
private void handleUnselectAll() {
|
||||
selectedContacts.clear();
|
||||
((CursorAdapter)getListView().getAdapter()).notifyDataSetChanged();
|
||||
}
|
||||
|
||||
private void selectAll() {
|
||||
Log.w("ContactSelectionListActivity", "Selecting all...");
|
||||
private void handleSelectAll() {
|
||||
selectedContacts.clear();
|
||||
|
||||
Cursor cursor = null;
|
||||
|
||||
try {
|
||||
cursor = ContactAccessor.getInstance().getCursorForContactsWithNumbers(this);
|
||||
cursor = ContactAccessor.getInstance().getCursorForContactsWithNumbers(getActivity());
|
||||
|
||||
while (cursor != null && cursor.moveToNext()) {
|
||||
ContactData contactData = ContactAccessor.getInstance().getContactData(this, cursor);
|
||||
ContactData contactData = ContactAccessor.getInstance().getContactData(getActivity(), cursor);
|
||||
|
||||
if (contactData.numbers.isEmpty()) continue;
|
||||
else if (contactData.numbers.size() == 1) addSingleNumberContact(contactData);
|
||||
@ -138,24 +137,6 @@ public class ContactSelectionListActivity extends ListActivity {
|
||||
((CursorAdapter)getListView().getAdapter()).notifyDataSetChanged();
|
||||
}
|
||||
|
||||
private void saveAndExit() {
|
||||
List<Recipient> recipientList = new LinkedList<Recipient>();
|
||||
|
||||
for (ContactData contactData : selectedContacts.values()) {
|
||||
for (NumberData numberData : contactData.numbers) {
|
||||
recipientList.add(new Recipient(contactData.name, numberData.number, null));
|
||||
}
|
||||
}
|
||||
|
||||
Intent resultIntent = getIntent();
|
||||
resultIntent.putExtra("recipients", new Recipients(recipientList));
|
||||
|
||||
if (getParent() == null) setResult(RESULT_OK, resultIntent);
|
||||
else getParent().setResult(RESULT_OK, resultIntent);
|
||||
|
||||
finish();
|
||||
}
|
||||
|
||||
private void addSingleNumberContact(ContactData contactData) {
|
||||
selectedContacts.put(contactData.id, contactData);
|
||||
}
|
||||
@ -172,7 +153,7 @@ public class ContactSelectionListActivity extends ListActivity {
|
||||
options[i++] = option.type + " " + option.number;
|
||||
}
|
||||
|
||||
AlertDialog.Builder builder = new AlertDialog.Builder(this);
|
||||
AlertDialog.Builder builder = new AlertDialog.Builder(getActivity());
|
||||
builder.setTitle("Select for " + contactData.name);
|
||||
builder.setMultiChoiceItems(options, null, new DiscriminatorClickedListener(contactData));
|
||||
builder.setPositiveButton("Ok", new DiscriminatorFinishedListener(contactData, textView));
|
||||
@ -180,10 +161,9 @@ public class ContactSelectionListActivity extends ListActivity {
|
||||
builder.show();
|
||||
}
|
||||
|
||||
private void displayContacts() {
|
||||
Cursor cursor = ContactAccessor.getInstance().getCursorForContactsWithNumbers(this);
|
||||
startManagingCursor(cursor);
|
||||
setListAdapter(new ContactSelectionListAdapter(this, cursor));
|
||||
private void initializeCursor() {
|
||||
setListAdapter(new ContactSelectionListAdapter(getActivity(), null));
|
||||
this.getLoaderManager().initLoader(0, null, this);
|
||||
}
|
||||
|
||||
private void initializeResources() {
|
||||
@ -191,7 +171,7 @@ public class ContactSelectionListActivity extends ListActivity {
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void onListItemClick(ListView l, View v, int position, long id) {
|
||||
public void onListItemClick(ListView l, View v, int position, long id) {
|
||||
((ContactItemView)v).selected();
|
||||
}
|
||||
|
||||
@ -327,4 +307,18 @@ public class ContactSelectionListActivity extends ListActivity {
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public Loader<Cursor> onCreateLoader(int arg0, Bundle arg1) {
|
||||
return ContactAccessor.getInstance().getCursorLoaderForContactsWithNumbers(getActivity());
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onLoadFinished(Loader<Cursor> arg0, Cursor cursor) {
|
||||
((CursorAdapter)getListAdapter()).changeCursor(cursor);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onLoaderReset(Loader<Cursor> arg0) {
|
||||
((CursorAdapter)getListAdapter()).changeCursor(null);
|
||||
}
|
||||
}
|
@ -16,29 +16,15 @@
|
||||
*/
|
||||
package org.thoughtcrime.securesms;
|
||||
|
||||
import java.util.HashMap;
|
||||
import java.util.LinkedList;
|
||||
import java.util.List;
|
||||
|
||||
import org.thoughtcrime.securesms.contacts.ContactAccessor;
|
||||
import org.thoughtcrime.securesms.contacts.ContactAccessor.ContactData;
|
||||
import org.thoughtcrime.securesms.contacts.ContactAccessor.NumberData;
|
||||
import org.thoughtcrime.securesms.recipients.Recipient;
|
||||
import org.thoughtcrime.securesms.recipients.Recipients;
|
||||
import org.thoughtcrime.securesms.util.RedPhoneCallTypes;
|
||||
|
||||
import android.app.ListActivity;
|
||||
import android.content.Context;
|
||||
import android.content.Intent;
|
||||
import android.database.Cursor;
|
||||
import android.os.Bundle;
|
||||
import android.provider.CallLog.Calls;
|
||||
import android.support.v4.app.LoaderManager;
|
||||
import android.support.v4.content.CursorLoader;
|
||||
import android.support.v4.content.Loader;
|
||||
import android.text.format.DateUtils;
|
||||
import android.util.Log;
|
||||
import android.view.KeyEvent;
|
||||
import android.view.LayoutInflater;
|
||||
import android.view.Menu;
|
||||
import android.view.MenuItem;
|
||||
import android.view.View;
|
||||
import android.view.ViewGroup;
|
||||
import android.widget.CheckedTextView;
|
||||
@ -48,6 +34,19 @@ import android.widget.ListView;
|
||||
import android.widget.RelativeLayout;
|
||||
import android.widget.TextView;
|
||||
|
||||
import com.actionbarsherlock.app.SherlockListFragment;
|
||||
|
||||
import org.thoughtcrime.securesms.contacts.ContactAccessor;
|
||||
import org.thoughtcrime.securesms.contacts.ContactAccessor.ContactData;
|
||||
import org.thoughtcrime.securesms.contacts.ContactAccessor.NumberData;
|
||||
import org.thoughtcrime.securesms.recipients.Recipient;
|
||||
import org.thoughtcrime.securesms.recipients.Recipients;
|
||||
import org.thoughtcrime.securesms.util.RedPhoneCallTypes;
|
||||
|
||||
import java.util.HashMap;
|
||||
import java.util.LinkedList;
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* Displays a list of recently used contacts for multi-select. Displayed
|
||||
* by the ContactSelectionActivity in a tab frame, and ultimately used by
|
||||
@ -56,51 +55,36 @@ import android.widget.TextView;
|
||||
* @author Moxie Marlinspike
|
||||
*
|
||||
*/
|
||||
public class ContactSelectionRecentActivity extends ListActivity {
|
||||
public class ContactSelectionRecentFragment extends SherlockListFragment
|
||||
implements LoaderManager.LoaderCallbacks<Cursor>
|
||||
{
|
||||
|
||||
private final HashMap<Long, ContactData> selectedContacts = new HashMap<Long, ContactData>();
|
||||
|
||||
private static final int MENU_OPTION_EXIT = 1;
|
||||
|
||||
@Override
|
||||
protected void onCreate(Bundle icicle) {
|
||||
super.onCreate(icicle);
|
||||
public void onActivityCreated(Bundle icicle) {
|
||||
super.onActivityCreated(icicle);
|
||||
|
||||
setContentView(R.layout.contact_selection_recent_activity);
|
||||
initializeResources();
|
||||
displayContacts();
|
||||
initializeCursor();
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean onPrepareOptionsMenu(Menu menu) {
|
||||
super.onPrepareOptionsMenu(menu);
|
||||
menu.clear();
|
||||
menu.add(0, MENU_OPTION_EXIT, Menu.NONE, "Finished!").setIcon(android.R.drawable.ic_menu_set_as);
|
||||
return true;
|
||||
public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
|
||||
return inflater.inflate(R.layout.contact_selection_recent_activity, container, false);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean onOptionsItemSelected(MenuItem item) {
|
||||
super.onOptionsItemSelected(item);
|
||||
|
||||
switch (item.getItemId()) {
|
||||
case MENU_OPTION_EXIT: saveAndExit(); return true;
|
||||
public void onListItemClick(ListView l, View v, int position, long id) {
|
||||
((CallItemView)v).selected();
|
||||
}
|
||||
|
||||
return false;
|
||||
private void initializeCursor() {
|
||||
setListAdapter(new ContactSelectionListAdapter(getActivity(), null));
|
||||
this.getLoaderManager().initLoader(0, null, this);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean onKeyDown(int keyCode, KeyEvent event) {
|
||||
if (keyCode == KeyEvent.KEYCODE_BACK && event.getRepeatCount() == 0) {
|
||||
saveAndExit();
|
||||
return true;
|
||||
}
|
||||
|
||||
return super.onKeyDown(keyCode, event);
|
||||
}
|
||||
|
||||
private void saveAndExit() {
|
||||
public Recipients getSelectedContacts() {
|
||||
List<Recipient> recipientList = new LinkedList<Recipient>();
|
||||
|
||||
for (ContactData contactData : selectedContacts.values()) {
|
||||
@ -109,13 +93,7 @@ public class ContactSelectionRecentActivity extends ListActivity {
|
||||
}
|
||||
}
|
||||
|
||||
Intent resultIntent = getIntent();
|
||||
resultIntent.putExtra("recipients", new Recipients(recipientList));
|
||||
|
||||
if (getParent() == null) setResult(RESULT_OK, resultIntent);
|
||||
else getParent().setResult(RESULT_OK, resultIntent);
|
||||
|
||||
finish();
|
||||
return new Recipients(recipientList);
|
||||
}
|
||||
|
||||
private void addSingleNumberContact(ContactData contactData) {
|
||||
@ -126,22 +104,10 @@ public class ContactSelectionRecentActivity extends ListActivity {
|
||||
selectedContacts.remove(contactData.id);
|
||||
}
|
||||
|
||||
private void displayContacts() {
|
||||
Cursor cursor = getContentResolver().query(Calls.CONTENT_URI, null, null, null, Calls.DEFAULT_SORT_ORDER);
|
||||
startManagingCursor(cursor);
|
||||
|
||||
setListAdapter(new ContactSelectionListAdapter(this, cursor));
|
||||
}
|
||||
|
||||
private void initializeResources() {
|
||||
this.getListView().setFocusable(true);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void onListItemClick(ListView l, View v, int position, long id) {
|
||||
((CallItemView)v).selected();
|
||||
}
|
||||
|
||||
private class ContactSelectionListAdapter extends CursorAdapter {
|
||||
|
||||
public ContactSelectionListAdapter(Context context, Cursor c) {
|
||||
@ -204,7 +170,7 @@ public class ContactSelectionRecentActivity extends ListActivity {
|
||||
|
||||
public void set(long id, String name, String label, String number, int type, long date) {
|
||||
if( name == null ) {
|
||||
name = ContactAccessor.getInstance().getNameForNumber(ContactSelectionRecentActivity.this, number);
|
||||
name = ContactAccessor.getInstance().getNameForNumber(getActivity(), number);
|
||||
}
|
||||
|
||||
this.line1.setText((name == null || name.equals("")) ? number : name);
|
||||
@ -231,4 +197,22 @@ public class ContactSelectionRecentActivity extends ListActivity {
|
||||
this.line1.setChecked(false);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public Loader<Cursor> onCreateLoader(int arg0, Bundle arg1) {
|
||||
return new CursorLoader(getActivity(), Calls.CONTENT_URI,
|
||||
null, null, null,
|
||||
Calls.DEFAULT_SORT_ORDER);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onLoadFinished(Loader<Cursor> arg0, Cursor cursor) {
|
||||
((CursorAdapter)getListAdapter()).changeCursor(cursor);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onLoaderReset(Loader<Cursor> arg0) {
|
||||
((CursorAdapter)getListAdapter()).changeCursor(null);
|
||||
}
|
||||
|
||||
}
|
@ -1,236 +0,0 @@
|
||||
/**
|
||||
* Copyright (C) 2011 Whisper Systems
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
package org.thoughtcrime.securesms;
|
||||
|
||||
import java.util.HashMap;
|
||||
import java.util.LinkedList;
|
||||
import java.util.List;
|
||||
|
||||
import org.thoughtcrime.securesms.contacts.ContactAccessor;
|
||||
import org.thoughtcrime.securesms.contacts.ContactAccessor.ContactData;
|
||||
import org.thoughtcrime.securesms.contacts.ContactAccessor.GroupData;
|
||||
import org.thoughtcrime.securesms.contacts.ContactAccessor.NumberData;
|
||||
import org.thoughtcrime.securesms.recipients.Recipient;
|
||||
import org.thoughtcrime.securesms.recipients.Recipients;
|
||||
|
||||
import android.app.ListActivity;
|
||||
import android.app.ProgressDialog;
|
||||
import android.content.Context;
|
||||
import android.content.Intent;
|
||||
import android.database.Cursor;
|
||||
import android.os.Bundle;
|
||||
import android.os.Handler;
|
||||
import android.os.Message;
|
||||
import android.util.Log;
|
||||
import android.view.KeyEvent;
|
||||
import android.view.LayoutInflater;
|
||||
import android.view.Menu;
|
||||
import android.view.MenuItem;
|
||||
import android.view.View;
|
||||
import android.view.ViewGroup;
|
||||
import android.widget.CheckedTextView;
|
||||
import android.widget.CursorAdapter;
|
||||
import android.widget.LinearLayout;
|
||||
import android.widget.ListView;
|
||||
|
||||
/**
|
||||
* An activity for selecting a list of "contact groups." Displayed
|
||||
* by ContactSelectionActivity in a tabbed frame, and ultimately called
|
||||
* by ComposeMessageActivity for selecting a list of recipients.
|
||||
*
|
||||
* @author Moxie Marlinspike
|
||||
*
|
||||
*/
|
||||
public class GroupSelectionListActivity extends ListActivity {
|
||||
|
||||
private final HashMap<Long, GroupData> selectedGroups = new HashMap<Long, GroupData>();
|
||||
|
||||
private static final int MENU_OPTION_EXIT = 1;
|
||||
|
||||
@Override
|
||||
protected void onCreate(Bundle icicle) {
|
||||
super.onCreate(icicle);
|
||||
|
||||
setContentView(R.layout.contact_selection_group_activity);
|
||||
initializeResources();
|
||||
displayGroups();
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean onPrepareOptionsMenu(Menu menu) {
|
||||
super.onPrepareOptionsMenu(menu);
|
||||
menu.clear();
|
||||
menu.add(0, MENU_OPTION_EXIT, Menu.NONE, "Finished!").setIcon(android.R.drawable.ic_menu_set_as);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean onOptionsItemSelected(MenuItem item) {
|
||||
super.onOptionsItemSelected(item);
|
||||
|
||||
switch (item.getItemId()) {
|
||||
case MENU_OPTION_EXIT: saveAndExit(); return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean onKeyDown(int keyCode, KeyEvent event) {
|
||||
if (keyCode == KeyEvent.KEYCODE_BACK && event.getRepeatCount() == 0) {
|
||||
saveAndExit();
|
||||
return true;
|
||||
}
|
||||
|
||||
return super.onKeyDown(keyCode, event);
|
||||
}
|
||||
|
||||
private void saveAndExit() {
|
||||
GroupAggregationHandler aggregator = new GroupAggregationHandler();
|
||||
aggregator.aggregateContactsAndExit();
|
||||
}
|
||||
|
||||
private void addGroup(GroupData groupData) {
|
||||
selectedGroups.put(groupData.id, groupData);
|
||||
}
|
||||
|
||||
private void removeGroup(GroupData groupData) {
|
||||
selectedGroups.remove(groupData.id);
|
||||
}
|
||||
|
||||
private void displayGroups() {
|
||||
Cursor cursor = ContactAccessor.getInstance().getCursorForContactGroups(this);
|
||||
|
||||
startManagingCursor(cursor);
|
||||
setListAdapter(new GroupSelectionListAdapter(this, cursor));
|
||||
}
|
||||
|
||||
private void initializeResources() {
|
||||
this.getListView().setFocusable(true);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void onListItemClick(ListView l, View v, int position, long id) {
|
||||
((GroupItemView)v).selected();
|
||||
}
|
||||
|
||||
private class GroupSelectionListAdapter extends CursorAdapter {
|
||||
|
||||
public GroupSelectionListAdapter(Context context, Cursor cursor) {
|
||||
super(context, cursor);
|
||||
}
|
||||
|
||||
@Override
|
||||
public View newView(Context context, Cursor cursor, ViewGroup parent) {
|
||||
GroupItemView view = new GroupItemView(context);
|
||||
bindView(view, context, cursor);
|
||||
return view;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void bindView(View view, Context context, Cursor cursor) {
|
||||
GroupData groupData = ContactAccessor.getInstance().getGroupData(GroupSelectionListActivity.this, cursor);
|
||||
((GroupItemView)view).set(groupData);
|
||||
}
|
||||
}
|
||||
|
||||
private class GroupItemView extends LinearLayout {
|
||||
private GroupData groupData;
|
||||
private CheckedTextView name;
|
||||
|
||||
public GroupItemView(Context context) {
|
||||
super(context);
|
||||
|
||||
LayoutInflater li = (LayoutInflater)context.getSystemService(Context.LAYOUT_INFLATER_SERVICE);
|
||||
li.inflate(R.layout.contact_selection_group_item, this, true);
|
||||
|
||||
this.name = (CheckedTextView)findViewById(R.id.name);
|
||||
}
|
||||
|
||||
public void selected() {
|
||||
name.toggle();
|
||||
|
||||
if (name.isChecked()) {
|
||||
addGroup(groupData);
|
||||
} else {
|
||||
removeGroup(groupData);
|
||||
}
|
||||
}
|
||||
|
||||
public void set(GroupData groupData) {
|
||||
this.groupData = groupData;
|
||||
|
||||
if (selectedGroups.containsKey(groupData.id))
|
||||
this.name.setChecked(true);
|
||||
else
|
||||
this.name.setChecked(false);
|
||||
|
||||
this.name.setText(groupData.name);
|
||||
}
|
||||
}
|
||||
|
||||
private class GroupAggregationHandler extends Handler implements Runnable {
|
||||
private List<Recipient> recipientList = new LinkedList<Recipient>();
|
||||
private ProgressDialog progressDialog;
|
||||
|
||||
public GroupAggregationHandler() {}
|
||||
|
||||
public void run() {
|
||||
recipientList.clear();
|
||||
|
||||
for (GroupData groupData : selectedGroups.values()) {
|
||||
List<ContactData> contactDataList = ContactAccessor.getInstance().getGroupMembership(GroupSelectionListActivity.this, groupData.id);
|
||||
|
||||
Log.w("GroupSelectionListActivity", "Got contacts in group: " + contactDataList.size());
|
||||
|
||||
for (ContactData contactData : contactDataList) {
|
||||
for (NumberData numberData : contactData.numbers) {
|
||||
recipientList.add(new Recipient(contactData.name, numberData.number, null));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
this.obtainMessage().sendToTarget();
|
||||
}
|
||||
|
||||
public void aggregateContactsAndExit() {
|
||||
progressDialog = new ProgressDialog(GroupSelectionListActivity.this);
|
||||
progressDialog.setTitle("Aggregating Contacts");
|
||||
progressDialog.setMessage("Aggregating group contacts...");
|
||||
progressDialog.setCancelable(false);
|
||||
progressDialog.setIndeterminate(true);
|
||||
progressDialog.setProgressStyle(ProgressDialog.STYLE_SPINNER);
|
||||
progressDialog.show();
|
||||
Log.w("GroupSelectionListActivity", "Showing group spinner...");
|
||||
new Thread(this).start();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void handleMessage(Message message) {
|
||||
progressDialog.dismiss();
|
||||
|
||||
Intent resultIntent = getIntent();
|
||||
resultIntent.putExtra("recipients", new Recipients(recipientList));
|
||||
|
||||
if (getParent() == null) setResult(RESULT_OK, resultIntent);
|
||||
else getParent().setResult(RESULT_OK, resultIntent);
|
||||
|
||||
finish();
|
||||
}
|
||||
}
|
||||
}
|
@ -16,19 +16,19 @@
|
||||
*/
|
||||
package org.thoughtcrime.securesms.contacts;
|
||||
|
||||
import java.util.LinkedList;
|
||||
import java.util.List;
|
||||
|
||||
import org.thoughtcrime.securesms.crypto.IdentityKey;
|
||||
|
||||
import android.content.ContentResolver;
|
||||
import android.content.Context;
|
||||
import android.content.Intent;
|
||||
import android.database.Cursor;
|
||||
import android.net.Uri;
|
||||
import android.os.Build;
|
||||
import android.os.Parcel;
|
||||
import android.os.Parcelable;
|
||||
import android.support.v4.content.CursorLoader;
|
||||
|
||||
import org.thoughtcrime.securesms.crypto.IdentityKey;
|
||||
|
||||
import java.util.LinkedList;
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* Android changed their contacts API pretty heavily between
|
||||
@ -44,29 +44,9 @@ public abstract class ContactAccessor {
|
||||
public static final int UNIQUE_ID = 0;
|
||||
public static final int DISPLAY_NAME = 1;
|
||||
|
||||
private static ContactAccessor sInstance;
|
||||
private static final ContactAccessor sInstance = new ContactAccessorNewApi();
|
||||
|
||||
public static synchronized ContactAccessor getInstance() {
|
||||
if (sInstance == null) {
|
||||
String className;
|
||||
|
||||
if (Integer.parseInt(Build.VERSION.SDK) <= Build.VERSION_CODES.DONUT)
|
||||
className = "ContactAccessorOldApi";
|
||||
else
|
||||
className = "ContactAccessorNewApi";
|
||||
|
||||
try {
|
||||
Class<? extends ContactAccessor> clazz =
|
||||
Class.forName("org.thoughtcrime.securesms.contacts." + className )
|
||||
.asSubclass(ContactAccessor.class);
|
||||
|
||||
sInstance = clazz.newInstance();
|
||||
|
||||
} catch (Exception e) {
|
||||
throw new AssertionError(e);
|
||||
}
|
||||
}
|
||||
|
||||
return sInstance;
|
||||
}
|
||||
|
||||
@ -78,6 +58,8 @@ public abstract class ContactAccessor {
|
||||
public abstract List<String> getNumbersForThreadSearchFilter(String constraint, ContentResolver contentResolver);
|
||||
public abstract List<ContactData> getGroupMembership(Context context, long groupId);
|
||||
public abstract Cursor getCursorForContactGroups(Context context);
|
||||
public abstract CursorLoader getCursorLoaderForContactGroups(Context context);
|
||||
public abstract CursorLoader getCursorLoaderForContactsWithNumbers(Context context);
|
||||
public abstract Cursor getCursorForContactsWithNumbers(Context context);
|
||||
public abstract GroupData getGroupData(Context context, Cursor cursor);
|
||||
public abstract ContactData getContactData(Context context, Cursor cursor);
|
||||
|
@ -16,15 +16,6 @@
|
||||
*/
|
||||
package org.thoughtcrime.securesms.contacts;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.util.ArrayList;
|
||||
import java.util.LinkedList;
|
||||
import java.util.List;
|
||||
|
||||
import org.thoughtcrime.securesms.crypto.IdentityKey;
|
||||
import org.thoughtcrime.securesms.crypto.InvalidKeyException;
|
||||
import org.thoughtcrime.securesms.util.Base64;
|
||||
|
||||
import android.content.ContentResolver;
|
||||
import android.content.ContentValues;
|
||||
import android.content.Context;
|
||||
@ -39,9 +30,19 @@ import android.provider.ContactsContract.Contacts;
|
||||
import android.provider.ContactsContract.Data;
|
||||
import android.provider.ContactsContract.PhoneLookup;
|
||||
import android.provider.ContactsContract.RawContacts;
|
||||
import android.support.v4.content.CursorLoader;
|
||||
import android.telephony.PhoneNumberUtils;
|
||||
import android.util.Log;
|
||||
|
||||
import org.thoughtcrime.securesms.crypto.IdentityKey;
|
||||
import org.thoughtcrime.securesms.crypto.InvalidKeyException;
|
||||
import org.thoughtcrime.securesms.util.Base64;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.util.ArrayList;
|
||||
import java.util.LinkedList;
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* Interface into the Android 2.x+ contacts operations.
|
||||
*
|
||||
@ -302,9 +303,21 @@ public class ContactAccessorNewApi extends ContactAccessor {
|
||||
}
|
||||
|
||||
@Override
|
||||
public Cursor getCursorForContactsWithNumbers(Context context) {
|
||||
public CursorLoader getCursorLoaderForContactsWithNumbers(Context context) {
|
||||
Uri uri = ContactsContract.Contacts.CONTENT_URI;
|
||||
String selection = ContactsContract.Contacts.HAS_PHONE_NUMBER + " = 1";
|
||||
return context.getContentResolver().query(ContactsContract.Contacts.CONTENT_URI, null, selection, null, ContactsContract.Contacts.DISPLAY_NAME + " ASC");
|
||||
|
||||
return new CursorLoader(context, uri, null, selection, null,
|
||||
ContactsContract.Contacts.DISPLAY_NAME + " ASC");
|
||||
}
|
||||
|
||||
@Override
|
||||
public Cursor getCursorForContactsWithNumbers(Context context) {
|
||||
Uri uri = ContactsContract.Contacts.CONTENT_URI;
|
||||
String selection = ContactsContract.Contacts.HAS_PHONE_NUMBER + " = 1";
|
||||
|
||||
return context.getContentResolver().query(uri, null, selection, null,
|
||||
ContactsContract.Contacts.DISPLAY_NAME + " ASC");
|
||||
}
|
||||
|
||||
private ContactData getContactData(Context context, String displayName, long id) {
|
||||
@ -345,6 +358,12 @@ public class ContactAccessorNewApi extends ContactAccessor {
|
||||
return context.getContentResolver().query(ContactsContract.Groups.CONTENT_URI, null, null, null, ContactsContract.Groups.TITLE + " ASC");
|
||||
}
|
||||
|
||||
@Override
|
||||
public CursorLoader getCursorLoaderForContactGroups(Context context) {
|
||||
return new CursorLoader(context, ContactsContract.Groups.CONTENT_URI,
|
||||
null, null, null, ContactsContract.Groups.TITLE + " ASC");
|
||||
}
|
||||
|
||||
@Override
|
||||
public List<ContactData> getGroupMembership(Context context, long groupId) {
|
||||
LinkedList<ContactData> contacts = new LinkedList<ContactData>();
|
||||
|
@ -1,328 +0,0 @@
|
||||
/**
|
||||
* Copyright (C) 2011 Whisper Systems
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
package org.thoughtcrime.securesms.contacts;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.LinkedList;
|
||||
import java.util.List;
|
||||
|
||||
import org.thoughtcrime.securesms.crypto.IdentityKey;
|
||||
|
||||
import android.content.ContentResolver;
|
||||
import android.content.Context;
|
||||
import android.content.Intent;
|
||||
import android.database.Cursor;
|
||||
import android.database.DatabaseUtils;
|
||||
import android.database.MergeCursor;
|
||||
import android.net.Uri;
|
||||
import android.provider.Contacts;
|
||||
import android.provider.Contacts.GroupMembership;
|
||||
import android.provider.Contacts.People;
|
||||
import android.provider.Contacts.Phones;
|
||||
import android.telephony.PhoneNumberUtils;
|
||||
import android.util.Log;
|
||||
import android.widget.Toast;
|
||||
|
||||
|
||||
/**
|
||||
* A contact interface into the 1.x API for older clients.
|
||||
*
|
||||
* @author Stuart Anderson
|
||||
*/
|
||||
|
||||
public class ContactAccessorOldApi extends ContactAccessor {
|
||||
|
||||
@SuppressWarnings("deprecation")
|
||||
private static final String SORT_ORDER = Phones.NAME + "," + Phones.TYPE;
|
||||
@SuppressWarnings("deprecation")
|
||||
private static final String[] PROJECTION_PHONE = {
|
||||
Phones._ID, // 0
|
||||
Phones.PERSON_ID, // 1
|
||||
Phones.TYPE, // 2
|
||||
Phones.NUMBER, // 3
|
||||
Phones.LABEL, // 4
|
||||
Phones.DISPLAY_NAME, // 5
|
||||
};
|
||||
|
||||
@SuppressWarnings("deprecation")
|
||||
@Override
|
||||
public Cursor getCursorForRecipientFilter(CharSequence constraint,
|
||||
ContentResolver mContentResolver) {
|
||||
String phone = "";
|
||||
String wherePhone = null;
|
||||
|
||||
String cons = null;
|
||||
if (constraint != null) {
|
||||
cons = constraint.toString();
|
||||
|
||||
if (RecipientsAdapter.usefulAsDigits(cons)) {
|
||||
phone = PhoneNumberUtils.convertKeypadLettersToDigits(cons);
|
||||
if (phone.equals(cons)) {
|
||||
phone = "";
|
||||
} else {
|
||||
phone = phone.trim();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
String filter = DatabaseUtils.sqlEscapeString(cons + '%');
|
||||
String filterLastName = DatabaseUtils.sqlEscapeString("% " + cons + '%');
|
||||
|
||||
StringBuilder s = new StringBuilder();
|
||||
s.append("((name LIKE ");
|
||||
s.append(filter);
|
||||
s.append(") OR (name LIKE ");
|
||||
s.append(filterLastName);
|
||||
s.append(") OR (REPLACE(REPLACE(REPLACE(REPLACE(number, ' ', ''), '(', ''), ')', ''), '-', '') LIKE ");
|
||||
s.append(filter);
|
||||
s.append("))");
|
||||
|
||||
wherePhone = s.toString();
|
||||
|
||||
Cursor phoneCursor = mContentResolver.query(Phones.CONTENT_URI,
|
||||
PROJECTION_PHONE,
|
||||
wherePhone,
|
||||
null,
|
||||
SORT_ORDER);
|
||||
|
||||
//dumpCursor(phoneCursor);
|
||||
|
||||
|
||||
if (phone.length() > 0) {
|
||||
ArrayList result = new ArrayList();
|
||||
result.add(Integer.valueOf(-1)); // ID
|
||||
result.add(Long.valueOf(-1)); // CONTACT_ID
|
||||
result.add(Integer.valueOf(Phones.TYPE_CUSTOM)); // TYPE
|
||||
result.add(phone); // NUMBER
|
||||
|
||||
/*
|
||||
* The "\u00A0" keeps Phone.getDisplayLabel() from deciding
|
||||
* to display the default label ("Home") next to the transformation
|
||||
* of the letters into numbers.
|
||||
*/
|
||||
result.add("\u00A0"); // LABEL
|
||||
result.add(cons); // NAME
|
||||
|
||||
ArrayList<ArrayList> wrap = new ArrayList<ArrayList>();
|
||||
wrap.add(result);
|
||||
|
||||
ArrayListCursor translated = new ArrayListCursor(PROJECTION_PHONE, wrap);
|
||||
|
||||
return new MergeCursor(new Cursor[] { translated, phoneCursor });
|
||||
} else {
|
||||
return phoneCursor;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@SuppressWarnings("deprecation")
|
||||
@Override
|
||||
public CharSequence phoneTypeToString(Context mContext, int type,
|
||||
CharSequence label) {
|
||||
return Phones.getDisplayLabel(mContext, type, label);
|
||||
}
|
||||
|
||||
public static void dumpCursor( Cursor c ) {
|
||||
c.moveToFirst();
|
||||
Log.d( "DC", "Begin:" );
|
||||
for( int i=0; i < c.getCount(); i++ ) {
|
||||
String rowStr = "";
|
||||
for( int j=0; j < c.getColumnCount(); j++ ) {
|
||||
rowStr = rowStr + c.getColumnName(j) + "=" + c.getString(j) +" ";
|
||||
}
|
||||
Log.d( "DC", rowStr + "\n" );
|
||||
c.moveToNext();
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public Intent getIntentForContactSelection() {
|
||||
return new Intent(Intent.ACTION_PICK, People.CONTENT_URI);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void insertIdentityKey(Context context, Uri uri, IdentityKey identityKey) {
|
||||
Toast.makeText(context, "Sorry, reading and writing identity keys to the contacts database is not supported on Android 1.X", Toast.LENGTH_LONG).show();
|
||||
}
|
||||
|
||||
@Override
|
||||
public IdentityKey importIdentityKey(Context context, Uri uri) {
|
||||
Toast.makeText(context, "Sorry, reading and writing identity keys to the contacts database is not supported on Android 1.X", Toast.LENGTH_LONG).show();
|
||||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getNameFromContact(Context context, Uri uri) {
|
||||
// TODO Auto-generated method stub
|
||||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public List<String> getNumbersForThreadSearchFilter(String constraint, ContentResolver contentResolver) {
|
||||
LinkedList<String> numberList = new LinkedList<String>();
|
||||
Cursor cursor = null;
|
||||
|
||||
try {
|
||||
cursor = contentResolver.query(Uri.withAppendedPath(Contacts.People.CONTENT_FILTER_URI, Uri.encode(constraint)),
|
||||
null, null, null, null);
|
||||
|
||||
while (cursor != null && cursor.moveToNext()) {
|
||||
String number = cursor.getString(cursor.getColumnIndexOrThrow(Contacts.Phones.NUMBER));
|
||||
if (number != null)
|
||||
numberList.add(number);
|
||||
}
|
||||
} finally {
|
||||
if (cursor != null)
|
||||
cursor.close();
|
||||
}
|
||||
|
||||
return numberList;
|
||||
}
|
||||
|
||||
@Override
|
||||
public NameAndNumber getNameAndNumberFromContact(Context context, Uri uri) {
|
||||
Cursor cursor = null;
|
||||
NameAndNumber result = new NameAndNumber();
|
||||
|
||||
try {
|
||||
cursor = context.getContentResolver().query(uri, null, null, null, null);
|
||||
|
||||
if (cursor != null && cursor.moveToFirst()) {
|
||||
result.name = cursor.getString(cursor.getColumnIndexOrThrow(People.NAME));
|
||||
result.number = cursor.getString(cursor.getColumnIndexOrThrow(People.NUMBER));
|
||||
|
||||
return result;
|
||||
}
|
||||
} finally {
|
||||
if (cursor != null)
|
||||
cursor.close();
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Cursor getCursorForContactsWithNumbers(Context context) {
|
||||
return context.getContentResolver().query(People.CONTENT_URI,new String[]{People._ID,People.DISPLAY_NAME},
|
||||
People.NUMBER + " NOT NULL", null, "UPPER( " + People.DISPLAY_NAME + " ) ASC");
|
||||
}
|
||||
|
||||
@Override
|
||||
public ContactData getContactData(Context context, Cursor cursor) {
|
||||
ContactData contactData = new ContactData();
|
||||
contactData.id = cursor.getLong(cursor.getColumnIndexOrThrow(People._ID));
|
||||
contactData.name = cursor.getString(cursor.getColumnIndexOrThrow(People.DISPLAY_NAME));
|
||||
contactData.numbers = getNumberDataForPersonId(context, contactData.id);
|
||||
|
||||
return contactData;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Cursor getCursorForContactGroups(Context context) {
|
||||
return context.getContentResolver().query(Contacts.Groups.CONTENT_URI, null, null, null, Contacts.Groups.NAME + " ASC");
|
||||
}
|
||||
|
||||
private LinkedList<NumberData> getNumberDataForPersonId(Context context, long personId) {
|
||||
LinkedList<NumberData> numbers = new LinkedList<NumberData>();
|
||||
Cursor numberCursor = context.getContentResolver().query(Phones.CONTENT_URI, null,
|
||||
Phones.PERSON_ID + " = ?",
|
||||
new String[] {personId+""}, null);
|
||||
try {
|
||||
while (numberCursor != null && numberCursor.moveToNext()) {
|
||||
numbers.add(new NumberData(Phones.getDisplayLabel(context, numberCursor.getInt(numberCursor.getColumnIndexOrThrow(Phones.TYPE)), "").toString(),
|
||||
numberCursor.getString(numberCursor.getColumnIndexOrThrow(Phones.NUMBER))));
|
||||
}
|
||||
} finally {
|
||||
if (numberCursor != null)
|
||||
numberCursor.close();
|
||||
}
|
||||
|
||||
return numbers;
|
||||
}
|
||||
|
||||
private ContactData getContactDataFromGroupMembership(Context context, Cursor cursor) {
|
||||
ContactData contactData = new ContactData();
|
||||
contactData.id = cursor.getLong(cursor.getColumnIndexOrThrow(GroupMembership.PERSON_ID));
|
||||
|
||||
Cursor personCursor = context.getContentResolver().query(Uri.withAppendedPath(People.CONTENT_URI, contactData.id+""), null, null, null, null);
|
||||
|
||||
try {
|
||||
if (personCursor == null || !personCursor.moveToFirst())
|
||||
throw new AssertionError("Non-existent user in group?");
|
||||
|
||||
contactData.name = personCursor.getString(personCursor.getColumnIndexOrThrow(People.DISPLAY_NAME));
|
||||
contactData.numbers = getNumberDataForPersonId(context, contactData.id);
|
||||
|
||||
return contactData;
|
||||
|
||||
} finally {
|
||||
if (personCursor != null)
|
||||
personCursor.close();
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public List<ContactData> getGroupMembership(Context context, long groupId) {
|
||||
LinkedList<ContactData> contacts = new LinkedList<ContactData>();
|
||||
Cursor groupMembershipCursor = context.getContentResolver().query(Contacts.GroupMembership.CONTENT_URI, null,
|
||||
GroupMembership.GROUP_ID + " = ?",
|
||||
new String[] {groupId+""}, null);
|
||||
|
||||
try {
|
||||
while (groupMembershipCursor != null && groupMembershipCursor.moveToNext()) {
|
||||
contacts.add(getContactDataFromGroupMembership(context, groupMembershipCursor));
|
||||
}
|
||||
} finally {
|
||||
if (groupMembershipCursor != null)
|
||||
groupMembershipCursor.close();
|
||||
}
|
||||
|
||||
return contacts;
|
||||
}
|
||||
|
||||
@Override
|
||||
public GroupData getGroupData(Context context, Cursor cursor) {
|
||||
GroupData groupData = new GroupData();
|
||||
groupData.id = cursor.getLong(cursor.getColumnIndexOrThrow(Contacts.Groups._ID));
|
||||
groupData.name = cursor.getString(cursor.getColumnIndexOrThrow(Contacts.Groups.NAME));
|
||||
|
||||
return groupData;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getNameForNumber(Context context, String number) {
|
||||
Cursor cursor = context.getContentResolver().query(Contacts.Phones.CONTENT_URI, null,
|
||||
Phones.NUMBER + " = ?",
|
||||
new String[] {number}, null);
|
||||
|
||||
try {
|
||||
if (cursor != null && cursor.moveToFirst())
|
||||
return cursor.getString(cursor.getColumnIndexOrThrow(Contacts.Phones.DISPLAY_NAME));
|
||||
} finally {
|
||||
if (cursor != null)
|
||||
cursor.close();
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Uri getContactsUri() {
|
||||
return Contacts.People.CONTENT_URI;
|
||||
}
|
||||
|
||||
}
|
@ -16,14 +16,14 @@
|
||||
*/
|
||||
package org.thoughtcrime.securesms.recipients;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.Iterator;
|
||||
import java.util.List;
|
||||
import android.os.Parcel;
|
||||
import android.os.Parcelable;
|
||||
|
||||
import org.thoughtcrime.securesms.util.NumberUtil;
|
||||
|
||||
import android.os.Parcel;
|
||||
import android.os.Parcelable;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Iterator;
|
||||
import java.util.List;
|
||||
|
||||
public class Recipients implements Parcelable {
|
||||
|
||||
@ -49,6 +49,10 @@ public class Recipients implements Parcelable {
|
||||
in.readTypedList(recipients, Recipient.CREATOR);
|
||||
}
|
||||
|
||||
public void append(Recipients recipients) {
|
||||
this.recipients.addAll(recipients.getRecipientsList());
|
||||
}
|
||||
|
||||
public Recipients truncateToSingleRecipient() {
|
||||
assert(!this.recipients.isEmpty());
|
||||
this.recipients = this.recipients.subList(0, 1);
|
||||
|