diff --git a/AndroidManifest.xml b/AndroidManifest.xml
index 4ccde5b2d4..98df604a46 100644
--- a/AndroidManifest.xml
+++ b/AndroidManifest.xml
@@ -142,6 +142,9 @@
+
diff --git a/res/layout/activity_select_contacts.xml b/res/layout/activity_select_contacts.xml
new file mode 100644
index 0000000000..e2604c048c
--- /dev/null
+++ b/res/layout/activity_select_contacts.xml
@@ -0,0 +1,46 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/res/menu/group_create.xml b/res/menu/group_create.xml
deleted file mode 100644
index 7c1044c62d..0000000000
--- a/res/menu/group_create.xml
+++ /dev/null
@@ -1,10 +0,0 @@
-
-
-
\ No newline at end of file
diff --git a/res/menu/menu_edit_closed_group.xml b/res/menu/menu_apply.xml
similarity index 62%
rename from res/menu/menu_edit_closed_group.xml
rename to res/menu/menu_apply.xml
index 1e8237e3af..9bddeb7fd1 100644
--- a/res/menu/menu_edit_closed_group.xml
+++ b/res/menu/menu_apply.xml
@@ -3,8 +3,9 @@
xmlns:app="http://schemas.android.com/apk/res-auto">
diff --git a/res/menu/menu_create_closed_group.xml b/res/menu/menu_done.xml
similarity index 63%
rename from res/menu/menu_create_closed_group.xml
rename to res/menu/menu_done.xml
index 75b41dcd68..9ee181de1e 100644
--- a/res/menu/menu_create_closed_group.xml
+++ b/res/menu/menu_done.xml
@@ -3,8 +3,9 @@
xmlns:app="http://schemas.android.com/apk/res-auto">
diff --git a/res/values/strings.xml b/res/values/strings.xml
index bc2001a3d6..e698ce54ee 100644
--- a/res/values/strings.xml
+++ b/res/values/strings.xml
@@ -1781,11 +1781,13 @@
One of the members of your group has an invalid Session ID
Are you sure you want to remove this user?
User removed from group
- Apply
+
Remove user from group
Make this user a group admin
+ Select Contacts
+
Join Open Group
Couldn\'t join group
Open Group URL
@@ -1878,4 +1880,7 @@
Closed Groups
Open Groups
+ Apply
+ Done
+
diff --git a/src/org/thoughtcrime/securesms/GroupCreateActivity.java b/src/org/thoughtcrime/securesms/GroupCreateActivity.java
index ede18c5061..17bba3300c 100644
--- a/src/org/thoughtcrime/securesms/GroupCreateActivity.java
+++ b/src/org/thoughtcrime/securesms/GroupCreateActivity.java
@@ -209,7 +209,7 @@ public class GroupCreateActivity extends PassphraseRequiredActionBarActivity
MenuInflater inflater = this.getMenuInflater();
menu.clear();
- inflater.inflate(R.menu.group_create, menu);
+ inflater.inflate(R.menu.menu_apply, menu);
super.onPrepareOptionsMenu(menu);
return true;
}
@@ -221,7 +221,7 @@ public class GroupCreateActivity extends PassphraseRequiredActionBarActivity
case android.R.id.home:
finish();
return true;
- case R.id.menu_create_group:
+ case R.id.applyButton:
if (groupToUpdate.isPresent()) handleGroupUpdate();
else handleGroupCreate();
return true;
@@ -389,7 +389,7 @@ public class GroupCreateActivity extends PassphraseRequiredActionBarActivity
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);
+ activity.findViewById(R.id.applyButton).setVisibility(View.GONE);
final int titleResId = activity.groupToUpdate.isPresent()
? R.string.GroupCreateActivity_updating_group
: R.string.GroupCreateActivity_creating_group;
@@ -401,7 +401,7 @@ public class GroupCreateActivity extends PassphraseRequiredActionBarActivity
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);
+ activity.findViewById(R.id.applyButton).setVisibility(View.VISIBLE);
}
}
diff --git a/src/org/thoughtcrime/securesms/loki/activities/CreateClosedGroupActivity.kt b/src/org/thoughtcrime/securesms/loki/activities/CreateClosedGroupActivity.kt
index f0989dc29b..23a959047e 100644
--- a/src/org/thoughtcrime/securesms/loki/activities/CreateClosedGroupActivity.kt
+++ b/src/org/thoughtcrime/securesms/loki/activities/CreateClosedGroupActivity.kt
@@ -30,7 +30,7 @@ class CreateClosedGroupActivity : PassphraseRequiredActionBarActivity(), MemberC
set(value) { field = value; createClosedGroupAdapter.members = value }
private val createClosedGroupAdapter by lazy {
- val result = CreateClosedGroupAdapter(this)
+ val result = SelectContactsAdapter(this)
result.glide = GlideApp.with(this)
result.memberClickListener = this
result
@@ -55,14 +55,14 @@ class CreateClosedGroupActivity : PassphraseRequiredActionBarActivity(), MemberC
}
override fun onCreateOptionsMenu(menu: Menu?): Boolean {
- menuInflater.inflate(R.menu.menu_create_closed_group, menu)
+ menuInflater.inflate(R.menu.menu_done, menu)
return members.isNotEmpty()
}
// endregion
// region Updating
override fun onCreateLoader(id: Int, bundle: Bundle?): Loader> {
- return CreateClosedGroupLoader(this)
+ return SelectContactsLoader(this)
}
override fun onLoadFinished(loader: Loader>, members: List) {
@@ -85,7 +85,7 @@ class CreateClosedGroupActivity : PassphraseRequiredActionBarActivity(), MemberC
override fun onOptionsItemSelected(item: MenuItem): Boolean {
val id = item.itemId
when(id) {
- R.id.createClosedGroupButton -> createClosedGroup()
+ R.id.doneButton -> createClosedGroup()
else -> { /* Do nothing */ }
}
return super.onOptionsItemSelected(item)
diff --git a/src/org/thoughtcrime/securesms/loki/activities/EditClosedGroupActivity.kt b/src/org/thoughtcrime/securesms/loki/activities/EditClosedGroupActivity.kt
index 2e6574cef9..d10b8d00cb 100644
--- a/src/org/thoughtcrime/securesms/loki/activities/EditClosedGroupActivity.kt
+++ b/src/org/thoughtcrime/securesms/loki/activities/EditClosedGroupActivity.kt
@@ -2,8 +2,6 @@ package org.thoughtcrime.securesms.loki.activities
import android.content.Context
import android.content.Intent
-import android.graphics.Bitmap
-import android.os.AsyncTask
import android.os.Bundle
import android.support.v4.app.LoaderManager
import android.support.v4.content.Loader
@@ -22,18 +20,13 @@ import kotlinx.android.synthetic.main.activity_linked_devices.recyclerView
import kotlinx.android.synthetic.main.activity_settings.*
import network.loki.messenger.R
import org.thoughtcrime.securesms.PassphraseRequiredActionBarActivity
-import org.thoughtcrime.securesms.conversation.ConversationActivity
import org.thoughtcrime.securesms.database.Address
import org.thoughtcrime.securesms.database.DatabaseFactory
-import org.thoughtcrime.securesms.database.ThreadDatabase
import org.thoughtcrime.securesms.groups.GroupManager
import org.thoughtcrime.securesms.loki.dialogs.GroupEditingOptionsBottomSheet
import org.thoughtcrime.securesms.mms.GlideApp
import org.thoughtcrime.securesms.recipients.Recipient
-import org.thoughtcrime.securesms.util.TextSecurePreferences
-import org.whispersystems.libsignal.util.guava.Optional
import org.whispersystems.signalservice.api.crypto.ProfileCipher
-import java.lang.ref.WeakReference
class EditClosedGroupActivity : PassphraseRequiredActionBarActivity(), MemberClickListener, LoaderManager.LoaderCallbacks> {
private var members = listOf()
@@ -42,8 +35,10 @@ class EditClosedGroupActivity : PassphraseRequiredActionBarActivity(), MemberCli
private var membersToRemove = setOf()
private var membersToAdd = setOf()
private var admins = setOf()
- private var displayNameToBeUploaded: String? = null
private val originalName by lazy { DatabaseFactory.getGroupDatabase(this).getGroup(groupID).get().title }
+ private var nameHasChanged = false
+ private lateinit var newGroupDisplayName: String
+
private val editClosedGroupAdapter by lazy {
val result = EditClosedGroupAdapter(this)
@@ -55,7 +50,6 @@ class EditClosedGroupActivity : PassphraseRequiredActionBarActivity(), MemberCli
set(value) { field = value; handleIsEditingDisplayNameChanged() }
companion object {
- public val createNewPrivateChatResultCode = 100
@JvmField
public val GROUP_ID = "GROUP_ID"
}
@@ -72,12 +66,12 @@ class EditClosedGroupActivity : PassphraseRequiredActionBarActivity(), MemberCli
saveEditButton.setOnClickListener { saveDisplayName() }
recyclerView.adapter = editClosedGroupAdapter
recyclerView.layoutManager = LinearLayoutManager(this)
- addMembersClosedGroupButton.setOnClickListener { createNewPrivateChat() }
+ addMembersClosedGroupButton.setOnClickListener { onAddMember() }
LoaderManager.getInstance(this).initLoader(0, null, this)
}
override fun onCreateOptionsMenu(menu: Menu?): Boolean {
- menuInflater.inflate(R.menu.menu_edit_closed_group, menu)
+ menuInflater.inflate(R.menu.menu_apply, menu)
return members.isNotEmpty()
}
// endregion
@@ -107,16 +101,11 @@ class EditClosedGroupActivity : PassphraseRequiredActionBarActivity(), MemberCli
override fun onOptionsItemSelected(item: MenuItem): Boolean {
val id = item.itemId
when(id) {
- R.id.editClosedGroupButton -> modifyClosedGroup()
- else -> { /* Do nothing */ }
+ R.id.applyButton -> modifyClosedGroup()
}
return super.onOptionsItemSelected(item)
}
- private fun createNewPrivateChat() {
- setResult(createNewPrivateChatResultCode)
- finish()
- }
private fun showEditDisplayNameUI() {
isEditingGroupName = true
}
@@ -137,15 +126,21 @@ class EditClosedGroupActivity : PassphraseRequiredActionBarActivity(), MemberCli
bottomSheet.show(supportFragmentManager, "closeBottomSheet")
}
+ private fun onAddMember() {
+ val intent = Intent(this@EditClosedGroupActivity, SelectContactsActivity::class.java)
+ startActivityForResult(intent, 124)
+ }
-
- private fun handleOpenConversation(threadId: Long, recipient: Recipient) {
- val intent = Intent(this, ConversationActivity::class.java)
- intent.putExtra(ConversationActivity.THREAD_ID_EXTRA, threadId)
- intent.putExtra(ConversationActivity.DISTRIBUTION_TYPE_EXTRA, ThreadDatabase.DistributionTypes.DEFAULT)
- intent.putExtra(ConversationActivity.ADDRESS_EXTRA, recipient.address)
- startActivity(intent)
- finish()
+ override fun onActivityResult(requestCode: Int, resultCode: Int, data: Intent?) {
+ super.onActivityResult(requestCode, resultCode, data)
+ if (resultCode == RESULT_OK) {
+ if (data != null && data.hasExtra("Selected Contacts Result")) {
+ val returnedContacts = data.extras.getStringArray("Selected Contacts Result")
+ var selectedContacts = returnedContacts.toSet()
+ membersToAdd = selectedContacts + membersToAdd
+ members = members + membersToAdd
+ }
+ }
}
private fun handleIsEditingDisplayNameChanged() {
@@ -163,7 +158,8 @@ class EditClosedGroupActivity : PassphraseRequiredActionBarActivity(), MemberCli
}
private fun saveDisplayName() {
- val groupDisplayName = displayNameEditText.text.toString().trim()
+ var groupDisplayName = displayNameEditText.text.toString().trim()
+ // something about the implementation of displayNameEdit text makes it null insead of whatever the user inputs, causes a crash
if (groupDisplayName.isEmpty()) {
return Toast.makeText(this, R.string.activity_settings_display_name_missing_error, Toast.LENGTH_SHORT).show()
}
@@ -174,13 +170,16 @@ class EditClosedGroupActivity : PassphraseRequiredActionBarActivity(), MemberCli
return Toast.makeText(this, R.string.activity_settings_display_name_too_long_error, Toast.LENGTH_SHORT).show()
}
isEditingGroupName = false
- displayNameToBeUploaded = groupDisplayName
+ nameHasChanged = true
+ newGroupDisplayName = groupDisplayName
+
}
+
private fun modifyClosedGroup() {
- if (originalName == displayNameToBeUploaded && membersToRemove.isEmpty() && membersToAdd.isEmpty()) { /* do nothing, close the activity and return to conversation */ } else {
+ if (!nameHasChanged && membersToRemove.isEmpty() && membersToAdd.isEmpty()) { finish() } else {
var groupDisplayName = originalName
- if (originalName != displayNameToBeUploaded) {
- groupDisplayName = displayNameToBeUploaded.toString()
+ if (nameHasChanged) {
+ groupDisplayName = newGroupDisplayName
}
val finalGroupMembers = members.map {
Recipient.from(this, Address.fromSerialized(it), false)
@@ -192,33 +191,4 @@ class EditClosedGroupActivity : PassphraseRequiredActionBarActivity(), MemberCli
finish()
}
}
- // endregion
-
- // region Tasks
- internal class EditClosedGroupTask(
- private val activity: WeakReference,
- private val groupID: String,
- private val profilePicture: Bitmap?,
- private val name: String?,
- private val members: Set,
- private val admins: Set
- ) : AsyncTask>() {
-
- override fun doInBackground(vararg params: Void?): Optional {
- val activity = activity.get() ?: return Optional.absent()
- return Optional.of(GroupManager.updateGroup(activity, groupID, members, profilePicture, name, admins))
- }
-
- override fun onPostExecute(result: Optional) {
- val activity = activity.get() ?: return super.onPostExecute(result)
- if (result.isPresent && result.get().threadId > -1) {
- if (!activity.isFinishing) {
- activity.handleOpenConversation(result.get().threadId, result.get().groupRecipient)
- }
- } else {
- super.onPostExecute(result)
- Toast.makeText(activity.applicationContext, R.string.activity_create_closed_group_invalid_session_id_error, Toast.LENGTH_LONG).show()
- }
- }
- }
}
\ No newline at end of file
diff --git a/src/org/thoughtcrime/securesms/loki/activities/EditClosedGroupLoader.kt b/src/org/thoughtcrime/securesms/loki/activities/EditClosedGroupLoader.kt
index 8b8bf276c2..59ef979994 100644
--- a/src/org/thoughtcrime/securesms/loki/activities/EditClosedGroupLoader.kt
+++ b/src/org/thoughtcrime/securesms/loki/activities/EditClosedGroupLoader.kt
@@ -12,28 +12,6 @@ class EditClosedGroupLoader(val groupID: String, context: Context) : AsyncLoader
return members.map {
it.address.toPhoneString()
}
+ /* To do: Load admins in the process here */
}
-
-/* For loading contacts for Add members, and loading admins from group list
-
- override fun loadContactsInBackground(): List {
- val contacts = ContactUtilities.getAllContacts(context)
- // Only show the master devices of the users we are friends with
- return contacts.filter { contact ->
- !contact.recipient.isGroupRecipient && contact.isFriend && !contact.isOurDevice && !contact.isSlave
- }.map {
- it.recipient.address.toPhoneString()
- }
- }
- override fun loadAdminsInBackground(): List {
- val contacts = ContactUtilities.getAllContacts(context)
- // Only show the master devices of the users we are friends with
- return contacts.filter { contact ->
- !contact.recipient.isGroupRecipient && contact.isFriend && !contact.isOurDevice && !contact.isSlave
- }.map {
- it.recipient.address.toPhoneString()
- }
- }
-
- */
}
\ No newline at end of file
diff --git a/src/org/thoughtcrime/securesms/loki/activities/SelectContactsActivity.kt b/src/org/thoughtcrime/securesms/loki/activities/SelectContactsActivity.kt
new file mode 100644
index 0000000000..9d73deb831
--- /dev/null
+++ b/src/org/thoughtcrime/securesms/loki/activities/SelectContactsActivity.kt
@@ -0,0 +1,101 @@
+package org.thoughtcrime.securesms.loki.activities
+
+import android.app.Activity
+import android.content.Intent
+import android.os.Bundle
+import android.support.v4.app.LoaderManager
+import android.support.v4.content.Loader
+import android.support.v7.widget.LinearLayoutManager
+import android.view.Menu
+import android.view.MenuItem
+import android.view.View
+import kotlinx.android.synthetic.main.activity_create_closed_group.*
+import kotlinx.android.synthetic.main.activity_linked_devices.recyclerView
+import network.loki.messenger.R
+import org.thoughtcrime.securesms.PassphraseRequiredActionBarActivity
+import org.thoughtcrime.securesms.mms.GlideApp
+
+class SelectContactsActivity : PassphraseRequiredActionBarActivity(), MemberClickListener, LoaderManager.LoaderCallbacks> {
+ private var members = listOf()
+ set(value) { field = value; selectContactsAdapter.members = value }
+
+ private val selectContactsAdapter by lazy {
+ val result = SelectContactsAdapter(this)
+ result.glide = GlideApp.with(this)
+ result.memberClickListener = this
+ result
+ }
+
+ private val selectedMembers: Set
+ get() { return selectContactsAdapter.selectedMembers }
+
+ companion object {
+ public val createNewPrivateChatResultCode = 100
+ }
+
+ // region Lifecycle
+ override fun onCreate(savedInstanceState: Bundle?, isReady: Boolean) {
+ super.onCreate(savedInstanceState, isReady)
+ setContentView(R.layout.activity_select_contacts)
+ supportActionBar!!.title = resources.getString(R.string.activity_select_contacts_title)
+ recyclerView.adapter = selectContactsAdapter
+ recyclerView.layoutManager = LinearLayoutManager(this)
+ createNewPrivateChatButton.setOnClickListener { createNewPrivateChat() }
+ LoaderManager.getInstance(this).initLoader(0, null, this)
+ }
+
+ override fun onCreateOptionsMenu(menu: Menu?): Boolean {
+ menuInflater.inflate(R.menu.menu_done, menu)
+ return members.isNotEmpty()
+ }
+ // endregion
+
+ // region Updating
+ override fun onCreateLoader(id: Int, bundle: Bundle?): Loader> {
+ return SelectContactsLoader(this)
+ }
+
+ override fun onLoadFinished(loader: Loader>, members: List) {
+ update(members)
+ }
+
+ override fun onLoaderReset(loader: Loader>) {
+ update(listOf())
+ }
+
+ private fun update(members: List) {
+ this.members = members
+ mainContentContainer.visibility = if (members.isEmpty()) View.GONE else View.VISIBLE
+ emptyStateContainer.visibility = if (members.isEmpty()) View.VISIBLE else View.GONE
+ invalidateOptionsMenu()
+ }
+ // endregion
+
+ // region Interaction
+ override fun onOptionsItemSelected(item: MenuItem): Boolean {
+ val id = item.itemId
+ when(id) {
+ R.id.doneButton -> returnContacts()
+ else -> { /* Do nothing */ }
+ }
+ return super.onOptionsItemSelected(item)
+ }
+
+ private fun createNewPrivateChat() {
+ setResult(createNewPrivateChatResultCode)
+ finish()
+ }
+
+ override fun onMemberClick(member: String) {
+ selectContactsAdapter.onMemberClick(member)
+ }
+
+ private fun returnContacts() {
+ val selectedMembers = this.selectedMembers
+ val selectedContacts = selectedMembers.toTypedArray()
+ val data = Intent()
+ data.putExtra("Selected Contacts Result", selectedContacts)
+ setResult(Activity.RESULT_OK, data)
+ finish()
+ }
+}
\ No newline at end of file
diff --git a/src/org/thoughtcrime/securesms/loki/activities/CreateClosedGroupAdapter.kt b/src/org/thoughtcrime/securesms/loki/activities/SelectContactsAdapter.kt
similarity index 92%
rename from src/org/thoughtcrime/securesms/loki/activities/CreateClosedGroupAdapter.kt
rename to src/org/thoughtcrime/securesms/loki/activities/SelectContactsAdapter.kt
index fa69ef8afa..886735b3a3 100644
--- a/src/org/thoughtcrime/securesms/loki/activities/CreateClosedGroupAdapter.kt
+++ b/src/org/thoughtcrime/securesms/loki/activities/SelectContactsAdapter.kt
@@ -8,7 +8,7 @@ import org.thoughtcrime.securesms.loki.views.UserView
import org.thoughtcrime.securesms.mms.GlideRequests
import org.thoughtcrime.securesms.recipients.Recipient
-class CreateClosedGroupAdapter(private val context: Context) : RecyclerView.Adapter() {
+class SelectContactsAdapter(private val context: Context) : RecyclerView.Adapter() {
lateinit var glide: GlideRequests
val selectedMembers = mutableSetOf()
var members = listOf()
diff --git a/src/org/thoughtcrime/securesms/loki/activities/CreateClosedGroupLoader.kt b/src/org/thoughtcrime/securesms/loki/activities/SelectContactsLoader.kt
similarity index 87%
rename from src/org/thoughtcrime/securesms/loki/activities/CreateClosedGroupLoader.kt
rename to src/org/thoughtcrime/securesms/loki/activities/SelectContactsLoader.kt
index 59422993e1..59a7ef6ad1 100644
--- a/src/org/thoughtcrime/securesms/loki/activities/CreateClosedGroupLoader.kt
+++ b/src/org/thoughtcrime/securesms/loki/activities/SelectContactsLoader.kt
@@ -4,7 +4,7 @@ import android.content.Context
import org.thoughtcrime.securesms.loki.utilities.ContactUtilities
import org.thoughtcrime.securesms.util.AsyncLoader
-class CreateClosedGroupLoader(context: Context) : AsyncLoader>(context) {
+class SelectContactsLoader(context: Context) : AsyncLoader>(context) {
override fun loadInBackground(): List {
val contacts = ContactUtilities.getAllContacts(context)