Refactor
parent
410bb9df43
commit
ed2ab2d78a
@ -1,4 +1,4 @@
|
||||
package org.thoughtcrime.securesms.loki.redesign.activities
|
||||
package org.thoughtcrime.securesms.loki.activities
|
||||
|
||||
import android.os.Bundle
|
||||
import network.loki.messenger.R
|
@ -1,4 +1,4 @@
|
||||
package org.thoughtcrime.securesms.loki.redesign.activities
|
||||
package org.thoughtcrime.securesms.loki.activities
|
||||
|
||||
import android.content.Intent
|
||||
import android.graphics.Bitmap
|
@ -1,10 +1,10 @@
|
||||
package org.thoughtcrime.securesms.loki.redesign.activities
|
||||
package org.thoughtcrime.securesms.loki.activities
|
||||
|
||||
import android.content.Context
|
||||
import android.support.v7.widget.RecyclerView
|
||||
import android.view.ViewGroup
|
||||
import org.thoughtcrime.securesms.database.Address
|
||||
import org.thoughtcrime.securesms.loki.redesign.views.UserView
|
||||
import org.thoughtcrime.securesms.loki.views.UserView
|
||||
import org.thoughtcrime.securesms.mms.GlideRequests
|
||||
import org.thoughtcrime.securesms.recipients.Recipient
|
||||
|
@ -1,7 +1,7 @@
|
||||
package org.thoughtcrime.securesms.loki.redesign.activities
|
||||
package org.thoughtcrime.securesms.loki.activities
|
||||
|
||||
import android.content.Context
|
||||
import org.thoughtcrime.securesms.loki.redesign.utilities.ContactUtilities
|
||||
import org.thoughtcrime.securesms.loki.utilities.ContactUtilities
|
||||
import org.thoughtcrime.securesms.util.AsyncLoader
|
||||
|
||||
class CreateClosedGroupLoader(context: Context) : AsyncLoader<List<String>>(context) {
|
@ -1,4 +1,4 @@
|
||||
package org.thoughtcrime.securesms.loki.redesign.activities
|
||||
package org.thoughtcrime.securesms.loki.activities
|
||||
|
||||
import android.content.Context
|
||||
import android.database.Cursor
|
@ -1,10 +1,10 @@
|
||||
package org.thoughtcrime.securesms.loki.redesign.activities
|
||||
package org.thoughtcrime.securesms.loki.activities
|
||||
|
||||
import android.content.Context
|
||||
import android.support.v7.widget.RecyclerView
|
||||
import android.view.ViewGroup
|
||||
import org.thoughtcrime.securesms.devicelist.Device
|
||||
import org.thoughtcrime.securesms.loki.redesign.views.DeviceView
|
||||
import org.thoughtcrime.securesms.loki.views.DeviceView
|
||||
|
||||
class LinkedDevicesAdapter(private val context: Context) : RecyclerView.Adapter<LinkedDevicesAdapter.ViewHolder>() {
|
||||
var devices = listOf<Device>()
|
@ -1,9 +1,9 @@
|
||||
package org.thoughtcrime.securesms.loki.redesign.activities
|
||||
package org.thoughtcrime.securesms.loki.activities
|
||||
|
||||
import android.content.Context
|
||||
import org.thoughtcrime.securesms.database.DatabaseFactory
|
||||
import org.thoughtcrime.securesms.devicelist.Device
|
||||
import org.thoughtcrime.securesms.loki.redesign.utilities.MnemonicUtilities
|
||||
import org.thoughtcrime.securesms.loki.utilities.MnemonicUtilities
|
||||
import org.thoughtcrime.securesms.util.AsyncLoader
|
||||
import org.thoughtcrime.securesms.util.TextSecurePreferences
|
||||
import org.whispersystems.signalservice.loki.protocol.multidevice.LokiDeviceLinkUtilities
|
@ -1,4 +1,4 @@
|
||||
package org.thoughtcrime.securesms.loki.redesign.activities
|
||||
package org.thoughtcrime.securesms.loki.activities
|
||||
|
||||
import android.os.Bundle
|
||||
import network.loki.messenger.R
|
@ -1,24 +1,20 @@
|
||||
package org.thoughtcrime.securesms.loki.redesign.activities
|
||||
package org.thoughtcrime.securesms.loki.activities
|
||||
|
||||
import android.app.AlertDialog
|
||||
import android.content.Intent
|
||||
import android.graphics.drawable.TransitionDrawable
|
||||
import android.os.Bundle
|
||||
import android.os.Handler
|
||||
import android.support.annotation.DrawableRes
|
||||
import android.view.View
|
||||
import android.widget.LinearLayout
|
||||
import android.widget.Toast
|
||||
import kotlinx.android.synthetic.main.activity_display_name.registerButton
|
||||
import kotlinx.android.synthetic.main.activity_home.*
|
||||
import kotlinx.android.synthetic.main.activity_pn_mode.*
|
||||
import network.loki.messenger.R
|
||||
import org.thoughtcrime.securesms.ApplicationContext
|
||||
import org.thoughtcrime.securesms.BaseActionBarActivity
|
||||
import org.thoughtcrime.securesms.database.DatabaseFactory
|
||||
import org.thoughtcrime.securesms.loki.redesign.utilities.setUpActionBarSessionLogo
|
||||
import org.thoughtcrime.securesms.loki.redesign.utilities.show
|
||||
import org.thoughtcrime.securesms.util.GroupUtil
|
||||
import org.thoughtcrime.securesms.loki.utilities.setUpActionBarSessionLogo
|
||||
import org.thoughtcrime.securesms.loki.utilities.show
|
||||
import org.thoughtcrime.securesms.util.TextSecurePreferences
|
||||
|
||||
class PNModeActivity : BaseActionBarActivity() {
|
@ -1,4 +1,4 @@
|
||||
package org.thoughtcrime.securesms.loki.redesign.activities
|
||||
package org.thoughtcrime.securesms.loki.activities
|
||||
|
||||
import android.os.Bundle
|
||||
import network.loki.messenger.R
|
@ -1,4 +1,4 @@
|
||||
package org.thoughtcrime.securesms.loki.redesign.activities
|
||||
package org.thoughtcrime.securesms.loki.activities
|
||||
|
||||
import android.content.ClipData
|
||||
import android.content.ClipboardManager
|
@ -1,4 +1,4 @@
|
||||
package org.thoughtcrime.securesms.loki.redesign.messaging
|
||||
package org.thoughtcrime.securesms.loki.api
|
||||
|
||||
import android.content.Context
|
||||
import android.content.Intent
|
@ -1,4 +1,4 @@
|
||||
package org.thoughtcrime.securesms.loki.redesign.messaging
|
||||
package org.thoughtcrime.securesms.loki.api
|
||||
|
||||
import android.content.Context
|
||||
import android.content.Intent
|
@ -1,10 +1,9 @@
|
||||
package org.thoughtcrime.securesms.loki.redesign.messaging
|
||||
package org.thoughtcrime.securesms.loki.api
|
||||
|
||||
import android.content.Context
|
||||
import android.os.Handler
|
||||
import android.util.Log
|
||||
import nl.komponents.kovenant.Promise
|
||||
import nl.komponents.kovenant.functional.bind
|
||||
import nl.komponents.kovenant.then
|
||||
import org.thoughtcrime.securesms.ApplicationContext
|
||||
import org.thoughtcrime.securesms.crypto.IdentityKeyUtil
|
@ -1,13 +1,13 @@
|
||||
package org.thoughtcrime.securesms.loki.redesign.messaging
|
||||
package org.thoughtcrime.securesms.loki.database
|
||||
|
||||
import android.content.ContentValues
|
||||
import android.content.Context
|
||||
import org.thoughtcrime.securesms.crypto.PreKeyUtil
|
||||
import org.thoughtcrime.securesms.database.Database
|
||||
import org.thoughtcrime.securesms.database.helpers.SQLCipherOpenHelper
|
||||
import org.thoughtcrime.securesms.loki.redesign.utilities.get
|
||||
import org.thoughtcrime.securesms.loki.redesign.utilities.getInt
|
||||
import org.thoughtcrime.securesms.loki.redesign.utilities.insertOrUpdate
|
||||
import org.thoughtcrime.securesms.loki.utilities.get
|
||||
import org.thoughtcrime.securesms.loki.utilities.getInt
|
||||
import org.thoughtcrime.securesms.loki.utilities.insertOrUpdate
|
||||
import org.whispersystems.libsignal.state.PreKeyRecord
|
||||
import org.whispersystems.signalservice.loki.database.LokiPreKeyRecordDatabaseProtocol
|
||||
|
@ -1,4 +1,4 @@
|
||||
package org.thoughtcrime.securesms.loki.redesign.dialogs
|
||||
package org.thoughtcrime.securesms.loki.dialogs
|
||||
|
||||
import android.app.Dialog
|
||||
import android.graphics.Color
|
@ -1,4 +1,4 @@
|
||||
package org.thoughtcrime.securesms.loki.redesign.dialogs
|
||||
package org.thoughtcrime.securesms.loki.dialogs
|
||||
|
||||
import android.os.Bundle
|
||||
import android.support.design.widget.BottomSheetDialogFragment
|
@ -1,4 +1,4 @@
|
||||
package org.thoughtcrime.securesms.loki.redesign.dialogs
|
||||
package org.thoughtcrime.securesms.loki.dialogs
|
||||
|
||||
import android.app.Dialog
|
||||
import android.graphics.Color
|
@ -1,4 +1,4 @@
|
||||
package org.thoughtcrime.securesms.loki.redesign.dialogs
|
||||
package org.thoughtcrime.securesms.loki.dialogs
|
||||
|
||||
import android.os.Bundle
|
||||
import android.support.design.widget.BottomSheetDialogFragment
|
@ -1,4 +1,4 @@
|
||||
package org.thoughtcrime.securesms.loki.redesign.dialogs
|
||||
package org.thoughtcrime.securesms.loki.dialogs
|
||||
|
||||
import android.app.AlertDialog
|
||||
import android.content.DialogInterface
|
@ -1,4 +1,4 @@
|
||||
package org.thoughtcrime.securesms.loki.redesign.dialogs
|
||||
package org.thoughtcrime.securesms.loki.dialogs
|
||||
|
||||
import android.app.Dialog
|
||||
import android.content.ClipData
|
@ -0,0 +1,85 @@
|
||||
package org.thoughtcrime.securesms.loki.fragments
|
||||
|
||||
import android.content.Context
|
||||
import android.support.v7.widget.RecyclerView
|
||||
import android.view.LayoutInflater
|
||||
import android.view.View
|
||||
import android.view.ViewGroup
|
||||
import kotlinx.android.synthetic.main.contact_selection_list_divider.view.*
|
||||
import network.loki.messenger.R
|
||||
import org.thoughtcrime.securesms.loki.views.UserView
|
||||
import org.thoughtcrime.securesms.mms.GlideRequests
|
||||
import org.thoughtcrime.securesms.recipients.Recipient
|
||||
|
||||
class ContactSelectionListAdapter(private val context: Context, private val multiSelect: Boolean) : RecyclerView.Adapter<RecyclerView.ViewHolder>() {
|
||||
lateinit var glide: GlideRequests
|
||||
val selectedContacts = mutableSetOf<Recipient>()
|
||||
var items = listOf<ContactSelectionListItem>()
|
||||
set(value) { field = value; notifyDataSetChanged() }
|
||||
var contactClickListener: ContactClickListener? = null
|
||||
|
||||
private object ViewType {
|
||||
const val Contact = 0
|
||||
const val Divider = 1
|
||||
}
|
||||
|
||||
class UserViewHolder(val view: UserView) : RecyclerView.ViewHolder(view)
|
||||
class DividerViewHolder(val view: View) : RecyclerView.ViewHolder(view)
|
||||
|
||||
override fun getItemCount(): Int {
|
||||
return items.size
|
||||
}
|
||||
|
||||
override fun getItemViewType(position: Int): Int {
|
||||
return when (items[position]) {
|
||||
is ContactSelectionListItem.Header -> ViewType.Divider
|
||||
else -> ViewType.Contact
|
||||
}
|
||||
}
|
||||
|
||||
override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): RecyclerView.ViewHolder {
|
||||
return if (viewType == ViewType.Contact) {
|
||||
UserViewHolder(UserView(context))
|
||||
} else {
|
||||
val view = LayoutInflater.from(context).inflate(R.layout.contact_selection_list_divider, parent, false)
|
||||
DividerViewHolder(view)
|
||||
}
|
||||
}
|
||||
|
||||
override fun onBindViewHolder(viewHolder: RecyclerView.ViewHolder, position: Int) {
|
||||
val item = items[position]
|
||||
if (viewHolder is UserViewHolder) {
|
||||
item as ContactSelectionListItem.Contact
|
||||
viewHolder.view.setOnClickListener { contactClickListener?.onContactClick(item.recipient) }
|
||||
val isSelected = selectedContacts.contains(item.recipient)
|
||||
viewHolder.view.bind(item.recipient, isSelected, glide)
|
||||
viewHolder.view.setCheckBoxVisible(multiSelect)
|
||||
} else if (viewHolder is DividerViewHolder) {
|
||||
item as ContactSelectionListItem.Header
|
||||
viewHolder.view.label.text = item.name
|
||||
}
|
||||
}
|
||||
|
||||
fun onContactClick(recipient: Recipient) {
|
||||
if (selectedContacts.contains(recipient)) {
|
||||
selectedContacts.remove(recipient)
|
||||
contactClickListener?.onContactDeselected(recipient)
|
||||
} else if (multiSelect || selectedContacts.isEmpty()) {
|
||||
selectedContacts.add(recipient)
|
||||
contactClickListener?.onContactSelected(recipient)
|
||||
}
|
||||
val index = items.indexOfFirst {
|
||||
when (it) {
|
||||
is ContactSelectionListItem.Header -> false
|
||||
is ContactSelectionListItem.Contact -> it.recipient == recipient
|
||||
}
|
||||
}
|
||||
notifyItemChanged(index)
|
||||
}
|
||||
}
|
||||
|
||||
interface ContactClickListener {
|
||||
fun onContactClick(contact: Recipient)
|
||||
fun onContactSelected(contact: Recipient)
|
||||
fun onContactDeselected(contact: Recipient)
|
||||
}
|
@ -0,0 +1,112 @@
|
||||
package org.thoughtcrime.securesms.loki.fragments
|
||||
|
||||
import android.os.Bundle
|
||||
import android.support.v4.app.Fragment
|
||||
import android.support.v4.app.LoaderManager
|
||||
import android.support.v4.content.Loader
|
||||
import android.support.v4.widget.SwipeRefreshLayout.OnRefreshListener
|
||||
import android.support.v7.widget.LinearLayoutManager
|
||||
import android.view.LayoutInflater
|
||||
import android.view.View
|
||||
import android.view.ViewGroup
|
||||
import kotlinx.android.synthetic.main.contact_selection_list_fragment.*
|
||||
import network.loki.messenger.R
|
||||
import org.thoughtcrime.securesms.contacts.ContactsCursorLoader
|
||||
import org.thoughtcrime.securesms.mms.GlideApp
|
||||
import org.thoughtcrime.securesms.recipients.Recipient
|
||||
|
||||
class ContactSelectionListFragment : Fragment(), LoaderManager.LoaderCallbacks<List<ContactSelectionListItem>>, ContactClickListener {
|
||||
private var cursorFilter: String? = null
|
||||
var onContactSelectedListener: OnContactSelectedListener? = null
|
||||
|
||||
val selectedContacts: List<String>
|
||||
get() = listAdapter.selectedContacts.map { it.address.serialize() }
|
||||
|
||||
private val multiSelect: Boolean by lazy {
|
||||
activity!!.intent.getBooleanExtra(MULTI_SELECT, false)
|
||||
}
|
||||
|
||||
private val listAdapter by lazy {
|
||||
val result = ContactSelectionListAdapter(activity!!, multiSelect)
|
||||
result.glide = GlideApp.with(this)
|
||||
result.contactClickListener = this
|
||||
result
|
||||
}
|
||||
|
||||
companion object {
|
||||
@JvmField val DISPLAY_MODE = "display_mode"
|
||||
@JvmField val MULTI_SELECT = "multi_select"
|
||||
@JvmField val REFRESHABLE = "refreshable"
|
||||
}
|
||||
|
||||
interface OnContactSelectedListener {
|
||||
fun onContactSelected(number: String?)
|
||||
fun onContactDeselected(number: String?)
|
||||
}
|
||||
|
||||
override fun onActivityCreated(savedInstanceState: Bundle?) {
|
||||
super.onActivityCreated(savedInstanceState)
|
||||
recyclerView.layoutManager = LinearLayoutManager(activity)
|
||||
recyclerView.adapter = listAdapter
|
||||
swipeRefreshLayout.isEnabled = activity!!.intent.getBooleanExtra(REFRESHABLE, true)
|
||||
}
|
||||
|
||||
override fun onStart() {
|
||||
super.onStart()
|
||||
LoaderManager.getInstance(this).initLoader(0, null, this)
|
||||
}
|
||||
|
||||
override fun onCreateView(inflater: LayoutInflater, container: ViewGroup?, savedInstanceState: Bundle?): View? {
|
||||
return inflater.inflate(R.layout.contact_selection_list_fragment, container, false)
|
||||
}
|
||||
|
||||
fun setQueryFilter(filter: String?) {
|
||||
cursorFilter = filter
|
||||
LoaderManager.getInstance(this).restartLoader(0, null, this)
|
||||
}
|
||||
|
||||
fun resetQueryFilter() {
|
||||
setQueryFilter(null)
|
||||
swipeRefreshLayout.isRefreshing = false
|
||||
}
|
||||
|
||||
fun setRefreshing(refreshing: Boolean) {
|
||||
swipeRefreshLayout.isRefreshing = refreshing
|
||||
}
|
||||
|
||||
fun setOnRefreshListener(onRefreshListener: OnRefreshListener?) {
|
||||
swipeRefreshLayout.setOnRefreshListener(onRefreshListener)
|
||||
}
|
||||
|
||||
override fun onCreateLoader(id: Int, args: Bundle?): Loader<List<ContactSelectionListItem>> {
|
||||
return ContactSelectionListLoader(activity!!,
|
||||
activity!!.intent.getIntExtra(DISPLAY_MODE, ContactsCursorLoader.DisplayMode.FLAG_ALL),
|
||||
cursorFilter)
|
||||
}
|
||||
|
||||
override fun onLoadFinished(loader: Loader<List<ContactSelectionListItem>>, items: List<ContactSelectionListItem>) {
|
||||
update(items)
|
||||
}
|
||||
|
||||
override fun onLoaderReset(loader: Loader<List<ContactSelectionListItem>>) {
|
||||
update(listOf())
|
||||
}
|
||||
|
||||
private fun update(items: List<ContactSelectionListItem>) {
|
||||
listAdapter.items = items
|
||||
mainContentContainer.visibility = if (items.isEmpty()) View.GONE else View.VISIBLE
|
||||
emptyStateContainer.visibility = if (items.isEmpty()) View.VISIBLE else View.GONE
|
||||
}
|
||||
|
||||
override fun onContactClick(contact: Recipient) {
|
||||
listAdapter.onContactClick(contact)
|
||||
}
|
||||
|
||||
override fun onContactSelected(contact: Recipient) {
|
||||
onContactSelectedListener?.onContactSelected(contact.address.serialize())
|
||||
}
|
||||
|
||||
override fun onContactDeselected(contact: Recipient) {
|
||||
onContactSelectedListener?.onContactDeselected(contact.address.serialize())
|
||||
}
|
||||
}
|
@ -0,0 +1,74 @@
|
||||
package org.thoughtcrime.securesms.loki.fragments
|
||||
|
||||
import android.content.Context
|
||||
import network.loki.messenger.R
|
||||
import org.thoughtcrime.securesms.loki.utilities.Contact
|
||||
import org.thoughtcrime.securesms.loki.utilities.ContactUtilities
|
||||
import org.thoughtcrime.securesms.recipients.Recipient
|
||||
import org.thoughtcrime.securesms.util.AsyncLoader
|
||||
|
||||
sealed class ContactSelectionListItem {
|
||||
class Header(val name: String) : ContactSelectionListItem()
|
||||
class Contact(val recipient: Recipient) : ContactSelectionListItem()
|
||||
}
|
||||
|
||||
class ContactSelectionListLoader(context: Context, val mode: Int, val filter: String?) : AsyncLoader<List<ContactSelectionListItem>>(context) {
|
||||
|
||||
object DisplayMode {
|
||||
const val FLAG_FRIENDS = 1
|
||||
const val FLAG_CLOSED_GROUPS = 1 shl 1
|
||||
const val FLAG_OPEN_GROUPS = 1 shl 2
|
||||
const val FLAG_ALL = FLAG_FRIENDS or FLAG_CLOSED_GROUPS or FLAG_OPEN_GROUPS
|
||||
}
|
||||
|
||||
private fun isFlagSet(flag: Int): Boolean {
|
||||
return mode and flag > 0
|
||||
}
|
||||
|
||||
override fun loadInBackground(): List<ContactSelectionListItem> {
|
||||
val contacts = ContactUtilities.getAllContacts(context).filter {
|
||||
if (filter.isNullOrEmpty()) return@filter true
|
||||
it.recipient.toShortString().contains(filter.trim(), true) || it.recipient.address.serialize().contains(filter.trim(), true)
|
||||
}.sortedBy {
|
||||
it.recipient.toShortString()
|
||||
}
|
||||
val list = mutableListOf<ContactSelectionListItem>()
|
||||
if (isFlagSet(DisplayMode.FLAG_CLOSED_GROUPS)) {
|
||||
list.addAll(getClosedGroups(contacts))
|
||||
}
|
||||
if (isFlagSet(DisplayMode.FLAG_OPEN_GROUPS)) {
|
||||
list.addAll(getOpenGroups(contacts))
|
||||
}
|
||||
if (isFlagSet(DisplayMode.FLAG_FRIENDS)) {
|
||||
list.addAll(getFriends(contacts))
|
||||
}
|
||||
return list
|
||||
}
|
||||
|
||||
private fun getFriends(contacts: List<Contact>): List<ContactSelectionListItem> {
|
||||
return getItems(contacts, context.getString(R.string.fragment_contact_selection_contacts_title)) {
|
||||
!it.recipient.isGroupRecipient && it.isFriend && !it.isOurDevice && !it.isSlave
|
||||
}
|
||||
}
|
||||
|
||||
private fun getClosedGroups(contacts: List<Contact>): List<ContactSelectionListItem> {
|
||||
return getItems(contacts, context.getString(R.string.fragment_contact_selection_closed_groups_title)) {
|
||||
it.recipient.address.isClosedGroup
|
||||
}
|
||||
}
|
||||
|
||||
private fun getOpenGroups(contacts: List<Contact>): List<ContactSelectionListItem> {
|
||||
return getItems(contacts, context.getString(R.string.fragment_contact_selection_open_groups_title)) {
|
||||
it.recipient.address.isOpenGroup
|
||||
}
|
||||
}
|
||||
|
||||
private fun getItems(contacts: List<Contact>, title: String, contactFilter: (Contact) -> Boolean): List<ContactSelectionListItem> {
|
||||
val items = contacts.filter(contactFilter).map {
|
||||
ContactSelectionListItem.Contact(it.recipient)
|
||||
}
|
||||
if (items.isEmpty()) return listOf()
|
||||
val header = ContactSelectionListItem.Header(title)
|
||||
return listOf(header) + items
|
||||
}
|
||||
}
|
@ -1,4 +1,4 @@
|
||||
package org.thoughtcrime.securesms.loki.redesign.fragments
|
||||
package org.thoughtcrime.securesms.loki.fragments
|
||||
|
||||
import android.content.res.Configuration
|
||||
import android.os.Bundle
|
@ -1,4 +1,4 @@
|
||||
package org.thoughtcrime.securesms.loki.redesign.fragments
|
||||
package org.thoughtcrime.securesms.loki.fragments
|
||||
|
||||
import android.os.Bundle
|
||||
import android.support.v4.app.Fragment
|
@ -1,4 +1,4 @@
|
||||
package org.thoughtcrime.securesms.loki.redesign.fragments
|
||||
package org.thoughtcrime.securesms.loki.fragments
|
||||
|
||||
import android.Manifest
|
||||
import android.content.pm.PackageManager
|
@ -0,0 +1,28 @@
|
||||
package org.thoughtcrime.securesms.loki.protocol
|
||||
|
||||
import android.content.Context
|
||||
import org.thoughtcrime.securesms.database.Address
|
||||
import org.thoughtcrime.securesms.database.DatabaseFactory
|
||||
import org.thoughtcrime.securesms.recipients.Recipient
|
||||
import org.thoughtcrime.securesms.sms.MessageSender
|
||||
import org.thoughtcrime.securesms.util.GroupUtil
|
||||
import org.thoughtcrime.securesms.util.TextSecurePreferences
|
||||
|
||||
object ClosedGroupsProtocol {
|
||||
|
||||
fun leaveGroup(context: Context, recipient: Recipient): Boolean {
|
||||
if (!recipient.address.isClosedGroup) { return true }
|
||||
val threadID = DatabaseFactory.getThreadDatabase(context).getThreadIdFor(recipient)
|
||||
val message = GroupUtil.createGroupLeaveMessage(context, recipient)
|
||||
if (threadID < 0 || !message.isPresent) { return false }
|
||||
MessageSender.send(context, message.get(), threadID, false, null)
|
||||
// Remove the *master* device from the group
|
||||
val masterHexPublicKey = TextSecurePreferences.getMasterHexEncodedPublicKey(context)
|
||||
val userPublicKey = masterHexPublicKey ?: TextSecurePreferences.getLocalNumber(context)
|
||||
val groupDatabase = DatabaseFactory.getGroupDatabase(context)
|
||||
val groupID = recipient.address.toGroupString()
|
||||
groupDatabase.setActive(groupID, false)
|
||||
groupDatabase.remove(groupID, Address.fromSerialized(userPublicKey))
|
||||
return true
|
||||
}
|
||||
}
|
@ -1,85 +0,0 @@
|
||||
package org.thoughtcrime.securesms.loki.redesign.fragments.contactselection
|
||||
|
||||
import android.content.Context
|
||||
import android.support.v7.widget.RecyclerView
|
||||
import android.view.LayoutInflater
|
||||
import android.view.View
|
||||
import android.view.ViewGroup
|
||||
import kotlinx.android.synthetic.main.contact_selection_list_divider.view.*
|
||||
import network.loki.messenger.R
|
||||
import org.thoughtcrime.securesms.loki.redesign.views.UserView
|
||||
import org.thoughtcrime.securesms.mms.GlideRequests
|
||||
import org.thoughtcrime.securesms.recipients.Recipient
|
||||
|
||||
class ContactSelectionListAdapter(private val context: Context, private val multiSelect: Boolean) : RecyclerView.Adapter<RecyclerView.ViewHolder>() {
|
||||
lateinit var glide: GlideRequests
|
||||
val selectedContacts = mutableSetOf<Recipient>()
|
||||
var items = listOf<ContactSelectionListItem>()
|
||||
set(value) { field = value; notifyDataSetChanged() }
|
||||
var contactClickListener: ContactClickListener? = null
|
||||
|
||||
private object ViewType {
|
||||
const val Contact = 0
|
||||
const val Divider = 1
|
||||
}
|
||||
|
||||
class UserViewHolder(val view: UserView) : RecyclerView.ViewHolder(view)
|
||||
class DividerViewHolder(val view: View) : RecyclerView.ViewHolder(view)
|
||||
|
||||
override fun getItemCount(): Int {
|
||||
return items.size
|
||||
}
|
||||
|
||||
override fun getItemViewType(position: Int): Int {
|
||||
return when (items[position]) {
|
||||
is ContactSelectionListItem.Header -> ViewType.Divider
|
||||
else -> ViewType.Contact
|
||||
}
|
||||
}
|
||||
|
||||
override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): RecyclerView.ViewHolder {
|
||||
return if (viewType == ViewType.Contact) {
|
||||
UserViewHolder(UserView(context))
|
||||
} else {
|
||||
val view = LayoutInflater.from(context).inflate(R.layout.contact_selection_list_divider, parent, false)
|
||||
DividerViewHolder(view)
|
||||
}
|
||||
}
|
||||
|
||||
override fun onBindViewHolder(viewHolder: RecyclerView.ViewHolder, position: Int) {
|
||||
val item = items[position]
|
||||
if (viewHolder is UserViewHolder) {
|
||||
item as ContactSelectionListItem.Contact
|
||||
viewHolder.view.setOnClickListener { contactClickListener?.onContactClick(item.recipient) }
|
||||
val isSelected = selectedContacts.contains(item.recipient)
|
||||
viewHolder.view.bind(item.recipient, isSelected, glide)
|
||||
viewHolder.view.setCheckBoxVisible(multiSelect)
|
||||
} else if (viewHolder is DividerViewHolder) {
|
||||
item as ContactSelectionListItem.Header
|
||||
viewHolder.view.label.text = item.name
|
||||
}
|
||||
}
|
||||
|
||||
fun onContactClick(recipient: Recipient) {
|
||||
if (selectedContacts.contains(recipient)) {
|
||||
selectedContacts.remove(recipient)
|
||||
contactClickListener?.onContactDeselected(recipient)
|
||||
} else if (multiSelect || selectedContacts.isEmpty()) {
|
||||
selectedContacts.add(recipient)
|
||||
contactClickListener?.onContactSelected(recipient)
|
||||
}
|
||||
val index = items.indexOfFirst {
|
||||
when (it) {
|
||||
is ContactSelectionListItem.Header -> false
|
||||
is ContactSelectionListItem.Contact -> it.recipient == recipient
|
||||
}
|
||||
}
|
||||
notifyItemChanged(index)
|
||||
}
|
||||
}
|
||||
|
||||
interface ContactClickListener {
|
||||
fun onContactClick(contact: Recipient)
|
||||
fun onContactSelected(contact: Recipient)
|
||||
fun onContactDeselected(contact: Recipient)
|
||||
}
|
@ -1,112 +0,0 @@
|
||||
package org.thoughtcrime.securesms.loki.redesign.fragments.contactselection
|
||||
|
||||
import android.os.Bundle
|
||||
import android.support.v4.app.Fragment
|
||||
import android.support.v4.app.LoaderManager
|
||||
import android.support.v4.content.Loader
|
||||
import android.support.v4.widget.SwipeRefreshLayout.OnRefreshListener
|
||||
import android.support.v7.widget.LinearLayoutManager
|
||||
import android.view.LayoutInflater
|
||||
import android.view.View
|
||||
import android.view.ViewGroup
|
||||
import kotlinx.android.synthetic.main.contact_selection_list_fragment.*
|
||||
import network.loki.messenger.R
|
||||
import org.thoughtcrime.securesms.contacts.ContactsCursorLoader
|
||||
import org.thoughtcrime.securesms.mms.GlideApp
|
||||
import org.thoughtcrime.securesms.recipients.Recipient
|
||||
|
||||
class ContactSelectionListFragment : Fragment(), LoaderManager.LoaderCallbacks<List<ContactSelectionListItem>>, ContactClickListener {
|
||||
private var cursorFilter: String? = null
|
||||
var onContactSelectedListener: OnContactSelectedListener? = null
|
||||
|
||||
val selectedContacts: List<String>
|
||||
get() = listAdapter.selectedContacts.map { it.address.serialize() }
|
||||
|
||||
private val multiSelect: Boolean by lazy {
|
||||
activity!!.intent.getBooleanExtra(MULTI_SELECT, false)
|
||||
}
|
||||
|
||||
private val listAdapter by lazy {
|
||||
val result = ContactSelectionListAdapter(activity!!, multiSelect)
|
||||
result.glide = GlideApp.with(this)
|
||||
result.contactClickListener = this
|
||||
result
|
||||
}
|
||||
|
||||
companion object {
|
||||
@JvmField val DISPLAY_MODE = "display_mode"
|
||||
@JvmField val MULTI_SELECT = "multi_select"
|
||||
@JvmField val REFRESHABLE = "refreshable"
|
||||
}
|
||||
|
||||
interface OnContactSelectedListener {
|
||||
fun onContactSelected(number: String?)
|
||||
fun onContactDeselected(number: String?)
|
||||
}
|
||||
|
||||
override fun onActivityCreated(savedInstanceState: Bundle?) {
|
||||
super.onActivityCreated(savedInstanceState)
|
||||
recyclerView.layoutManager = LinearLayoutManager(activity)
|
||||
recyclerView.adapter = listAdapter
|
||||
swipeRefreshLayout.isEnabled = activity!!.intent.getBooleanExtra(REFRESHABLE, true)
|
||||
}
|
||||
|
||||
override fun onStart() {
|
||||
super.onStart()
|
||||
LoaderManager.getInstance(this).initLoader(0, null, this)
|
||||
}
|
||||
|
||||
override fun onCreateView(inflater: LayoutInflater, container: ViewGroup?, savedInstanceState: Bundle?): View? {
|
||||
return inflater.inflate(R.layout.contact_selection_list_fragment, container, false)
|
||||
}
|
||||
|
||||
fun setQueryFilter(filter: String?) {
|
||||
cursorFilter = filter
|
||||
LoaderManager.getInstance(this).restartLoader(0, null, this)
|
||||
}
|
||||
|
||||
fun resetQueryFilter() {
|
||||
setQueryFilter(null)
|
||||
swipeRefreshLayout.isRefreshing = false
|
||||
}
|
||||
|
||||
fun setRefreshing(refreshing: Boolean) {
|
||||
swipeRefreshLayout.isRefreshing = refreshing
|
||||
}
|
||||
|
||||
fun setOnRefreshListener(onRefreshListener: OnRefreshListener?) {
|
||||
swipeRefreshLayout.setOnRefreshListener(onRefreshListener)
|
||||
}
|
||||
|
||||
override fun onCreateLoader(id: Int, args: Bundle?): Loader<List<ContactSelectionListItem>> {
|
||||
return ContactSelectionListLoader(activity!!,
|
||||
activity!!.intent.getIntExtra(DISPLAY_MODE, ContactsCursorLoader.DisplayMode.FLAG_ALL),
|
||||
cursorFilter)
|
||||
}
|
||||
|
||||
override fun onLoadFinished(loader: Loader<List<ContactSelectionListItem>>, items: List<ContactSelectionListItem>) {
|
||||
update(items)
|
||||
}
|
||||
|
||||
override fun onLoaderReset(loader: Loader<List<ContactSelectionListItem>>) {
|
||||
update(listOf())
|
||||
}
|
||||
|
||||
private fun update(items: List<ContactSelectionListItem>) {
|
||||
listAdapter.items = items
|
||||
mainContentContainer.visibility = if (items.isEmpty()) View.GONE else View.VISIBLE
|
||||
emptyStateContainer.visibility = if (items.isEmpty()) View.VISIBLE else View.GONE
|
||||
}
|
||||
|
||||
override fun onContactClick(contact: Recipient) {
|
||||
listAdapter.onContactClick(contact)
|
||||
}
|
||||
|
||||
override fun onContactSelected(contact: Recipient) {
|
||||
onContactSelectedListener?.onContactSelected(contact.address.serialize())
|
||||
}
|
||||
|
||||
override fun onContactDeselected(contact: Recipient) {
|
||||
onContactSelectedListener?.onContactDeselected(contact.address.serialize())
|
||||
}
|
||||
}
|
@ -1,83 +0,0 @@
|
||||
package org.thoughtcrime.securesms.loki.redesign.fragments.contactselection
|
||||
|
||||
import android.content.Context
|
||||
import network.loki.messenger.R
|
||||
import org.thoughtcrime.securesms.loki.redesign.utilities.Contact
|
||||
import org.thoughtcrime.securesms.loki.redesign.utilities.ContactUtilities
|
||||
import org.thoughtcrime.securesms.recipients.Recipient
|
||||
import org.thoughtcrime.securesms.util.AsyncLoader
|
||||
|
||||
sealed class ContactSelectionListItem {
|
||||
class Header(val name: String) : ContactSelectionListItem()
|
||||
class Contact(val recipient: Recipient) : ContactSelectionListItem()
|
||||
}
|
||||
|
||||
class ContactSelectionListLoader(context: Context, val mode: Int, val filter: String?) : AsyncLoader<List<ContactSelectionListItem>>(context) {
|
||||
|
||||
object DisplayMode {
|
||||
const val FLAG_FRIENDS = 1
|
||||
const val FLAG_CLOSED_GROUPS = 1 shl 1
|
||||
const val FLAG_OPEN_GROUPS = 1 shl 2
|
||||
const val FLAG_ALL = FLAG_FRIENDS or FLAG_CLOSED_GROUPS or FLAG_OPEN_GROUPS
|
||||
}
|
||||
|
||||
private fun isFlagSet(flag: Int): Boolean {
|
||||
return mode and flag > 0
|
||||
}
|
||||
|
||||
override fun loadInBackground(): List<ContactSelectionListItem> {
|
||||
val contacts = ContactUtilities.getAllContacts(context).filter {
|
||||
if (filter.isNullOrEmpty()) return@filter true
|
||||
|
||||
it.recipient.toShortString().contains(filter.trim(), true) || it.recipient.address.serialize().contains(filter.trim(), true)
|
||||
}.sortedBy {
|
||||
it.recipient.toShortString()
|
||||
}
|
||||
|
||||
val list = mutableListOf<ContactSelectionListItem>()
|
||||
|
||||
if (isFlagSet(DisplayMode.FLAG_CLOSED_GROUPS)) {
|
||||
list.addAll(getClosedGroups(contacts))
|
||||
}
|
||||
|
||||
if (isFlagSet(DisplayMode.FLAG_OPEN_GROUPS)) {
|
||||
list.addAll(getOpenGroups(contacts))
|
||||
}
|
||||
|
||||
if (isFlagSet(DisplayMode.FLAG_FRIENDS)) {
|
||||
list.addAll(getFriends(contacts))
|
||||
}
|
||||
|
||||
return list
|
||||
}
|
||||
|
||||
private fun getFriends(contacts: List<Contact>): List<ContactSelectionListItem> {
|
||||
return getItems(contacts, context.getString(R.string.fragment_contact_selection_contacts_title)) {
|
||||
!it.recipient.isGroupRecipient && it.isFriend && !it.isOurDevice && !it.isSlave
|
||||
}
|
||||
}
|
||||
|
||||
private fun getClosedGroups(contacts: List<Contact>): List<ContactSelectionListItem> {
|
||||
return getItems(contacts, context.getString(R.string.fragment_contact_selection_closed_groups_title)) {
|
||||
it.recipient.address.isSignalGroup
|
||||
}
|
||||
}
|
||||
|
||||
private fun getOpenGroups(contacts: List<Contact>): List<ContactSelectionListItem> {
|
||||
return getItems(contacts, context.getString(R.string.fragment_contact_selection_open_groups_title)) {
|
||||
it.recipient.address.isPublicChat
|
||||
}
|
||||
}
|
||||
|
||||
private fun getItems(contacts: List<Contact>, title: String, contactFilter: (Contact) -> Boolean): List<ContactSelectionListItem> {
|
||||
val items = contacts.filter(contactFilter).map {
|
||||
ContactSelectionListItem.Contact(it.recipient)
|
||||
}
|
||||
|
||||
if (items.isEmpty()) return listOf()
|
||||
|
||||
val header = ContactSelectionListItem.Header(title)
|
||||
|
||||
return listOf(header) + items
|
||||
}
|
||||
}
|
Some files were not shown because too many files have changed in this diff Show More
Loading…
Reference in New Issue