diff --git a/jni/dc_wrapper.c b/jni/dc_wrapper.c
index 72b933137..34110ae11 100644
--- a/jni/dc_wrapper.c
+++ b/jni/dc_wrapper.c
@@ -434,9 +434,9 @@ JNIEXPORT jint Java_com_b44t_messenger_DcContext_createGroupChat(JNIEnv *env, jo
}
-JNIEXPORT jint Java_com_b44t_messenger_DcContext_isContactInChat(JNIEnv *env, jobject obj, jint chat_id, jint contact_id)
+JNIEXPORT jboolean Java_com_b44t_messenger_DcContext_isContactInChat(JNIEnv *env, jobject obj, jint chat_id, jint contact_id)
{
- return (jint)dc_is_contact_in_chat(get_dc_context(env, obj), chat_id, contact_id);
+ return (jboolean)dc_is_contact_in_chat(get_dc_context(env, obj), chat_id, contact_id);
}
diff --git a/res/values/strings.xml b/res/values/strings.xml
index 6f0d06fac..821e2578d 100644
--- a/res/values/strings.xml
+++ b/res/values/strings.xml
@@ -316,6 +316,7 @@
New group
+ New verified group
Edit group
Group name
New MMS group
@@ -1427,5 +1428,6 @@
Type email address above
New chat
https://delta.chat/en/help
+ Please enter a name for the group.
diff --git a/src/com/b44t/messenger/DcContext.java b/src/com/b44t/messenger/DcContext.java
index 3d3e4e66e..086191287 100644
--- a/src/com/b44t/messenger/DcContext.java
+++ b/src/com/b44t/messenger/DcContext.java
@@ -119,7 +119,7 @@ public class DcContext {
public native int createChatByContactId(int contact_id);
public native int createChatByMsgId (int msg_id);
public native int createGroupChat (boolean verified, String name);
- public native int isContactInChat (int chat_id, int contact_id);
+ public native boolean isContactInChat (int chat_id, int contact_id);
public native int addContactToChat (int chat_id, int contact_id);
public native int removeContactFromChat(int chat_id, int contact_id);
public native void setDraft (int chat_id, String draft/*null=delete*/);
diff --git a/src/org/thoughtcrime/securesms/ContactSelectionListFragment.java b/src/org/thoughtcrime/securesms/ContactSelectionListFragment.java
index bdeaa18fe..67e770b1e 100644
--- a/src/org/thoughtcrime/securesms/ContactSelectionListFragment.java
+++ b/src/org/thoughtcrime/securesms/ContactSelectionListFragment.java
@@ -38,6 +38,7 @@ import android.widget.Button;
import android.widget.TextView;
import android.widget.Toast;
+import com.b44t.messenger.DcContext;
import com.pnikosis.materialishprogress.ProgressWheel;
import org.thoughtcrime.securesms.components.RecyclerViewFastScroller;
@@ -68,10 +69,11 @@ public class ContactSelectionListFragment extends Fragment
@SuppressWarnings("unused")
private static final String TAG = ContactSelectionListFragment.class.getSimpleName();
- public static final String DISPLAY_MODE = "display_mode";
- public static final String MULTI_SELECT = "multi_select";
- public static final String REFRESHABLE = "refreshable";
- public static final String RECENTS = "recents";
+ public static final String DISPLAY_MODE = "display_mode";
+ public static final String MULTI_SELECT = "multi_select";
+ public static final String REFRESHABLE = "refreshable";
+ public static final String RECENTS = "recents";
+ public static final String SELECT_VERIFIED_EXTRA = "select_verified";
private TextView emptyText;
private Set selectedContacts;
@@ -156,6 +158,10 @@ public class ContactSelectionListFragment extends Fragment
return getActivity().getIntent().getBooleanExtra(MULTI_SELECT, false);
}
+ private boolean isSelectVerfied() {
+ return getActivity().getIntent().getBooleanExtra(SELECT_VERIFIED_EXTRA, false);
+ }
+
private void initializeCursor() {
ContactSelectionListAdapter adapter = new ContactSelectionListAdapter(getActivity(),
GlideApp.with(this),
@@ -212,7 +218,12 @@ public class ContactSelectionListFragment extends Fragment
@Override
public Loader onCreateLoader(int id, Bundle args) {
- return new DcContactsLoader(getActivity(), 0, cursorFilter);
+ boolean addCreateGroupLinks = !isMulti();
+ int listflags = 0;
+ if(isSelectVerfied()) {
+ listflags = DcContext.DC_GCL_VERIFIED_ONLY;
+ }
+ return new DcContactsLoader(getActivity(), listflags, cursorFilter, addCreateGroupLinks);
}
@Override
diff --git a/src/org/thoughtcrime/securesms/GroupCreateActivity.java b/src/org/thoughtcrime/securesms/GroupCreateActivity.java
index 9b06a2d08..685256807 100644
--- a/src/org/thoughtcrime/securesms/GroupCreateActivity.java
+++ b/src/org/thoughtcrime/securesms/GroupCreateActivity.java
@@ -25,8 +25,6 @@ import android.os.AsyncTask;
import android.os.Bundle;
import android.support.annotation.NonNull;
import android.support.annotation.Nullable;
-import android.text.TextUtils;
-import android.util.Log;
import android.view.Menu;
import android.view.MenuInflater;
import android.view.MenuItem;
@@ -44,6 +42,8 @@ import com.soundcloud.android.crop.Crop;
import org.thoughtcrime.securesms.components.PushRecipientsPanel;
import org.thoughtcrime.securesms.components.PushRecipientsPanel.RecipientsPanelChangedListener;
+import org.thoughtcrime.securesms.connect.ApplicationDcContext;
+import org.thoughtcrime.securesms.connect.DcHelper;
import org.thoughtcrime.securesms.contacts.ContactsCursorLoader.DisplayMode;
import org.thoughtcrime.securesms.contacts.RecipientsEditor;
import org.thoughtcrime.securesms.contacts.avatars.ContactColors;
@@ -53,8 +53,6 @@ import org.thoughtcrime.securesms.database.DatabaseFactory;
import org.thoughtcrime.securesms.database.GroupDatabase;
import org.thoughtcrime.securesms.database.GroupDatabase.GroupRecord;
import org.thoughtcrime.securesms.database.ThreadDatabase;
-import org.thoughtcrime.securesms.groups.GroupManager;
-import org.thoughtcrime.securesms.groups.GroupManager.GroupActionResult;
import org.thoughtcrime.securesms.mms.GlideApp;
import org.thoughtcrime.securesms.recipients.Recipient;
import org.thoughtcrime.securesms.util.BitmapUtil;
@@ -65,7 +63,6 @@ import org.thoughtcrime.securesms.util.SelectedRecipientsAdapter.OnRecipientDele
import org.thoughtcrime.securesms.util.ViewUtil;
import org.thoughtcrime.securesms.util.task.ProgressDialogAsyncTask;
import org.whispersystems.libsignal.util.guava.Optional;
-import org.whispersystems.signalservice.api.util.InvalidNumberException;
import java.io.File;
import java.util.Collection;
@@ -88,6 +85,7 @@ public class GroupCreateActivity extends PassphraseRequiredActionBarActivity
public static final String GROUP_ADDRESS_EXTRA = "group_recipient";
public static final String GROUP_THREAD_EXTRA = "group_thread";
+ public static final String GROUP_CREATE_VERIFIED_EXTRA = "group_create_verified";
private final DynamicTheme dynamicTheme = new DynamicTheme();
private final DynamicLanguage dynamicLanguage = new DynamicLanguage();
@@ -95,6 +93,9 @@ public class GroupCreateActivity extends PassphraseRequiredActionBarActivity
private static final int PICK_CONTACT = 1;
public static final int AVATAR_SIZE = 210;
+ private ApplicationDcContext dcContext;
+
+ private boolean createVerified;
private EditText groupName;
private ListView lv;
private ImageView avatar;
@@ -111,8 +112,10 @@ public class GroupCreateActivity extends PassphraseRequiredActionBarActivity
@Override
protected void onCreate(Bundle state, boolean ready) {
+ dcContext = DcHelper.getContext(this);
setContentView(R.layout.group_create_activity);
//noinspection ConstantConditions
+ createVerified = getIntent().getBooleanExtra(GROUP_CREATE_VERIFIED_EXTRA, false);
getSupportActionBar().setDisplayHomeAsUpEnabled(true);
initializeResources();
initializeExistingGroup();
@@ -130,9 +133,18 @@ public class GroupCreateActivity extends PassphraseRequiredActionBarActivity
private void updateViewState() {
avatar.setEnabled(true);
groupName.setEnabled(true);
- getSupportActionBar().setTitle(groupToUpdate.isPresent()
- ? R.string.GroupCreateActivity_actionbar_edit_title
- : R.string.GroupCreateActivity_actionbar_title);
+
+ String title;
+ if(groupToUpdate.isPresent()) {
+ title = getString(R.string.GroupCreateActivity_actionbar_edit_title);
+ }
+ else if(createVerified) {
+ title = getString(R.string.GroupCreateActivity_actionbar_verified_title);
+ }
+ else {
+ title = getString(R.string.GroupCreateActivity_actionbar_title);
+ }
+ getSupportActionBar().setTitle(title);
}
private void addSelectedContacts(@NonNull Recipient... recipients) {
@@ -206,25 +218,47 @@ public class GroupCreateActivity extends PassphraseRequiredActionBarActivity
}
private void handleGroupCreate() {
- if (getAdapter().getCount() < 1) {
- Log.i(TAG, getString(R.string.GroupCreateActivity_contacts_no_members));
- Toast.makeText(getApplicationContext(), R.string.GroupCreateActivity_contacts_no_members, Toast.LENGTH_SHORT).show();
+ String groupName = getGroupName();
+ if(groupName==null) {
+ Toast.makeText(this, getString(R.string.GroupCreateActivity_please_enter_group_name), Toast.LENGTH_LONG).show();
return;
}
- new CreateSignalGroupTask(this, avatarBmp, getGroupName(), getAdapter().getRecipients()).executeOnExecutor(AsyncTask.THREAD_POOL_EXECUTOR);
+
+ int chatId = dcContext.createGroupChat(createVerified, groupName);
+
+ Set members = getAdapter().getRecipients();
+ for(Recipient member : members) {
+ Address address = member.getAddress();
+ if(address.isDcContact()) {
+ int contactId = address.getDcContactId();
+ dcContext.addContactToChat(chatId, contactId);
+ }
+ }
+
+ // TODO: handle avatarBmp
+
+ Intent intent = new Intent(this, ConversationActivity.class);
+ intent.putExtra(ConversationActivity.THREAD_ID_EXTRA, (long)chatId);
+ intent.putExtra(ConversationActivity.DISTRIBUTION_TYPE_EXTRA, ThreadDatabase.DistributionTypes.DEFAULT);
+ intent.putExtra(ConversationActivity.ADDRESS_EXTRA, Address.fromChat(dcContext.getChat((int)chatId)));
+ startActivity(intent);
+ finish();
}
private void handleGroupUpdate() {
- new UpdateSignalGroupTask(this, groupToUpdate.get().id, avatarBmp,
- getGroupName(), getAdapter().getRecipients()).executeOnExecutor(AsyncTask.THREAD_POOL_EXECUTOR);
- }
+ int chatId = 0;// TODO: get correct id from groupToUpdate.get().id; or so
+
+ String groupName = getGroupName();
+ if(groupName!=null) {
+ dcContext.setChatName(chatId, groupName);
+ }
+
+ // TODO: compare dcContext.getChatContacts(chatId); against getAdapter().getRecipients();
+ // and add/remove contacts
+
+
+ // TODO: handle avatarBmp
- private void handleOpenConversation(long threadId, Recipient recipient) {
- Intent intent = new Intent(this, ConversationActivity.class);
- intent.putExtra(ConversationActivity.THREAD_ID_EXTRA, threadId);
- intent.putExtra(ConversationActivity.DISTRIBUTION_TYPE_EXTRA, ThreadDatabase.DistributionTypes.DEFAULT);
- intent.putExtra(ConversationActivity.ADDRESS_EXTRA, recipient.getAddress());
- startActivity(intent);
finish();
}
@@ -233,7 +267,14 @@ public class GroupCreateActivity extends PassphraseRequiredActionBarActivity
}
private @Nullable String getGroupName() {
- return groupName.getText() != null ? groupName.getText().toString() : null;
+ String ret = groupName.getText() != null ? groupName.getText().toString() : null;
+ if(ret!=null) {
+ ret = ret.trim();
+ if(ret.isEmpty()) {
+ ret = null;
+ }
+ }
+ return ret;
}
@Override
@@ -280,6 +321,7 @@ public class GroupCreateActivity extends PassphraseRequiredActionBarActivity
@Override
public void onClick(View v) {
Intent intent = new Intent(GroupCreateActivity.this, PushContactSelectionActivity.class);
+ intent.putExtra(ContactSelectionListFragment.SELECT_VERIFIED_EXTRA, createVerified);
if (groupToUpdate.isPresent()) {
intent.putExtra(ContactSelectionListFragment.DISPLAY_MODE, DisplayMode.FLAG_PUSH);
} else {
@@ -289,105 +331,6 @@ public class GroupCreateActivity extends PassphraseRequiredActionBarActivity
}
}
- private abstract static class SignalGroupTask extends AsyncTask> {
-
- protected GroupCreateActivity activity;
- protected Bitmap avatar;
- protected Set members;
- protected String name;
-
- public SignalGroupTask(GroupCreateActivity activity,
- Bitmap avatar,
- String name,
- Set members)
- {
- this.activity = activity;
- this.avatar = avatar;
- this.name = name;
- this.members = members;
- }
-
- @Override
- protected void onPreExecute() {
- activity.findViewById(R.id.group_details_layout).setVisibility(View.GONE);
- activity.findViewById(R.id.creating_group_layout).setVisibility(View.VISIBLE);
- activity.findViewById(R.id.menu_create_group).setVisibility(View.GONE);
- final int titleResId = activity.groupToUpdate.isPresent()
- ? R.string.GroupCreateActivity_updating_group
- : R.string.GroupCreateActivity_creating_group;
- activity.creatingText.setText(activity.getString(titleResId, activity.getGroupName()));
- }
-
- @Override
- protected void onPostExecute(Optional groupActionResultOptional) {
- if (activity.isFinishing()) return;
- activity.findViewById(R.id.group_details_layout).setVisibility(View.VISIBLE);
- activity.findViewById(R.id.creating_group_layout).setVisibility(View.GONE);
- activity.findViewById(R.id.menu_create_group).setVisibility(View.VISIBLE);
- }
- }
-
- private static class CreateSignalGroupTask extends SignalGroupTask {
- public CreateSignalGroupTask(GroupCreateActivity activity, Bitmap avatar, String name, Set members) {
- super(activity, avatar, name, members);
- }
-
- @Override
- protected Optional doInBackground(Void... aVoid) {
- return Optional.of(GroupManager.createGroup(activity, members, avatar, name, false));
- }
-
- @Override
- protected void onPostExecute(Optional result) {
- if (result.isPresent() && result.get().getThreadId() > -1) {
- if (!activity.isFinishing()) {
- activity.handleOpenConversation(result.get().getThreadId(), result.get().getGroupRecipient());
- }
- } else {
- super.onPostExecute(result);
- Toast.makeText(activity.getApplicationContext(),
- R.string.GroupCreateActivity_contacts_invalid_number, Toast.LENGTH_LONG).show();
- }
- }
- }
-
- private static class UpdateSignalGroupTask extends SignalGroupTask {
- private String groupId;
-
- public UpdateSignalGroupTask(GroupCreateActivity activity, String groupId,
- Bitmap avatar, String name, Set members)
- {
- super(activity, avatar, name, members);
- this.groupId = groupId;
- }
-
- @Override
- protected Optional doInBackground(Void... aVoid) {
- try {
- return Optional.of(GroupManager.updateGroup(activity, groupId, members, avatar, name));
- } catch (InvalidNumberException e) {
- return Optional.absent();
- }
- }
-
- @Override
- protected void onPostExecute(Optional result) {
- if (result.isPresent() && result.get().getThreadId() > -1) {
- if (!activity.isFinishing()) {
- Intent intent = activity.getIntent();
- intent.putExtra(GROUP_THREAD_EXTRA, result.get().getThreadId());
- intent.putExtra(GROUP_ADDRESS_EXTRA, result.get().getGroupRecipient().getAddress());
- activity.setResult(RESULT_OK, intent);
- activity.finish();
- }
- } else {
- super.onPostExecute(result);
- Toast.makeText(activity.getApplicationContext(),
- R.string.GroupCreateActivity_contacts_invalid_number, Toast.LENGTH_LONG).show();
- }
- }
- }
-
private static class AddMembersTask extends AsyncTask> {
static class Result {
Optional recipient;
@@ -418,12 +361,17 @@ public class GroupCreateActivity extends PassphraseRequiredActionBarActivity
@Override
protected void onPostExecute(List results) {
if (activity.isFinishing()) return;
+ ApplicationDcContext dcContext = DcHelper.getContext(activity);
for (Result result : results) {
- if (result.recipient.isPresent()) {
- activity.getAdapter().add(result.recipient.get(), true);
- } else {
- Toast.makeText(activity, result.reason, Toast.LENGTH_SHORT).show();
+ Recipient recipient = result.recipient.get();
+ Address address = recipient.getAddress();
+ if(address.isDcContact()) {
+ activity.getAdapter().add(recipient, true);
+ }
+ else if(dcContext.mayBeValidAddr(address.toString())) {
+ int contactId = DcHelper.getContext(activity).createContact(null, address.toString());
+ activity.getAdapter().add(dcContext.getRecipient(dcContext.getContact(contactId)), true);
}
}
activity.updateViewState();
diff --git a/src/org/thoughtcrime/securesms/NewConversationActivity.java b/src/org/thoughtcrime/securesms/NewConversationActivity.java
index bcdd134a9..07a10d803 100644
--- a/src/org/thoughtcrime/securesms/NewConversationActivity.java
+++ b/src/org/thoughtcrime/securesms/NewConversationActivity.java
@@ -59,6 +59,7 @@ public class NewConversationActivity extends ContactSelectionActivity {
final DcContext dcContext = DcHelper.getContext(this);
if(specialId==DcContact.DC_CONTACT_ID_NEW_GROUP || specialId==DcContact.DC_CONTACT_ID_NEW_VERIFIED_GROUP) {
Intent intent = new Intent(this, GroupCreateActivity.class);
+ intent.putExtra(GroupCreateActivity.GROUP_CREATE_VERIFIED_EXTRA, specialId==DcContact.DC_CONTACT_ID_NEW_VERIFIED_GROUP);
startActivity(intent);
finish();
}
diff --git a/src/org/thoughtcrime/securesms/connect/DcContactsLoader.java b/src/org/thoughtcrime/securesms/connect/DcContactsLoader.java
index 3b005274d..46f772854 100644
--- a/src/org/thoughtcrime/securesms/connect/DcContactsLoader.java
+++ b/src/org/thoughtcrime/securesms/connect/DcContactsLoader.java
@@ -15,13 +15,15 @@ public class DcContactsLoader extends AsyncLoader {
private static final String TAG = DcContactsLoader.class.getName();
- private final int listflags;
- private final String query;
+ private final int listflags;
+ private final String query;
+ private final boolean addCreateGroupLinks;
- public DcContactsLoader(Context context, int listflags, String query) {
+ public DcContactsLoader(Context context, int listflags, String query, boolean addCreateGroupLinks) {
super(context);
- this.listflags = listflags;
- this.query = (query==null||query.isEmpty())? null : query;
+ this.listflags = listflags;
+ this.query = (query==null||query.isEmpty())? null : query;
+ this.addCreateGroupLinks = addCreateGroupLinks;
}
@Override
@@ -31,12 +33,12 @@ public class DcContactsLoader extends AsyncLoader {
int[] contact_ids = dcContext.getContacts(listflags, query);
if(query!=null) {
// show the "new contact" link also for partly typed e-mail addresses, so that the user knows he can continue
- if( dcContext.lookupContactIdByAddr(query)==0) {
+ if (dcContext.lookupContactIdByAddr(query)==0 && (listflags&DcContext.DC_GCL_VERIFIED_ONLY)==0) {
contact_ids = ArrayUtils.appendInt(contact_ids, DcContact.DC_CONTACT_ID_NEW_CONTACT);
}
return new DcContactsLoader.Ret(contact_ids, query);
}
- else {
+ else if(addCreateGroupLinks) {
// add "new group" and "new verified group" links
final int additional_items = 2; // if someone knows an easier way to prepend sth. to int[] please pr :)
int all_ids[] = new int[contact_ids.length+additional_items];
@@ -47,6 +49,9 @@ public class DcContactsLoader extends AsyncLoader {
}
return new DcContactsLoader.Ret(all_ids, query);
}
+ else {
+ return new DcContactsLoader.Ret(contact_ids, query);
+ }
}
public class Ret {
diff --git a/src/org/thoughtcrime/securesms/util/SelectedRecipientsAdapter.java b/src/org/thoughtcrime/securesms/util/SelectedRecipientsAdapter.java
index 6ddded9bf..929fc1bf9 100644
--- a/src/org/thoughtcrime/securesms/util/SelectedRecipientsAdapter.java
+++ b/src/org/thoughtcrime/securesms/util/SelectedRecipientsAdapter.java
@@ -99,7 +99,11 @@ public class SelectedRecipientsAdapter extends BaseAdapter {
final RecipientWrapper rw = (RecipientWrapper)getItem(position);
final Recipient p = rw.getRecipient();
final boolean modifiable = rw.isModifiable();
- final DcContact dcContact = dcContext.getContact(p.getAddress().getDcContactId());
+ DcContact dcContact = new DcContact(0);
+
+ if(p.getAddress().isDcContact()) {
+ dcContact = dcContext.getContact(p.getAddress().getDcContactId());
+ }
TextView name = (TextView) v.findViewById(R.id.name);
TextView phone = (TextView) v.findViewById(R.id.phone);