🎉 Separate messages by identity
Also, allow deleting all messages/conversations in a list
This commit is contained in:
parent
9f2508c1a5
commit
a9602368fb
@ -85,10 +85,10 @@ class AddressListFragment : AbstractItemListFragment<Void, BitmessageAddress>()
|
||||
super.onResume()
|
||||
|
||||
initFab(activity as MainActivity)
|
||||
updateList()
|
||||
reloadList()
|
||||
}
|
||||
|
||||
fun updateList() {
|
||||
override fun reloadList() {
|
||||
adapter.clear()
|
||||
context?.let { context ->
|
||||
val addressRepo = Singleton.getAddressRepository(context)
|
||||
@ -138,7 +138,7 @@ class AddressListFragment : AbstractItemListFragment<Void, BitmessageAddress>()
|
||||
}
|
||||
}
|
||||
|
||||
override fun updateList(label: Void) = updateList()
|
||||
override fun updateList(label: Void) = reloadList()
|
||||
|
||||
private data class ViewHolder(
|
||||
val ctx: Context,
|
||||
|
@ -33,6 +33,7 @@ import ch.dissem.apps.abit.listener.ListSelectionListener
|
||||
import ch.dissem.apps.abit.repository.AndroidMessageRepository
|
||||
import ch.dissem.apps.abit.service.Singleton
|
||||
import ch.dissem.apps.abit.service.Singleton.currentLabel
|
||||
import ch.dissem.apps.abit.util.preferences
|
||||
import ch.dissem.bitmessage.entity.Conversation
|
||||
import ch.dissem.bitmessage.entity.valueobject.Label
|
||||
import ch.dissem.bitmessage.utils.ConversationService
|
||||
@ -43,7 +44,9 @@ import com.h6ah4i.android.widget.advrecyclerview.touchguard.RecyclerViewTouchAct
|
||||
import com.h6ah4i.android.widget.advrecyclerview.utils.WrapperAdapterUtils
|
||||
import io.github.kobakei.materialfabspeeddial.FabSpeedDialMenu
|
||||
import kotlinx.android.synthetic.main.fragment_message_list.*
|
||||
import org.jetbrains.anko.cancelButton
|
||||
import org.jetbrains.anko.doAsync
|
||||
import org.jetbrains.anko.support.v4.alert
|
||||
import org.jetbrains.anko.support.v4.onUiThread
|
||||
import org.jetbrains.anko.uiThread
|
||||
import java.util.*
|
||||
@ -90,6 +93,7 @@ class ConversationListFragment : Fragment(), ListHolder<Label> {
|
||||
}
|
||||
|
||||
private var emptyTrashMenuItem: MenuItem? = null
|
||||
private var deleteAllMenuItem: MenuItem? = null
|
||||
private lateinit var messageRepo: AndroidMessageRepository
|
||||
private lateinit var conversationService: ConversationService
|
||||
private var activateOnItemClick: Boolean = false
|
||||
@ -103,7 +107,8 @@ class ConversationListFragment : Fragment(), ListHolder<Label> {
|
||||
val conversationIds = messageRepo.findConversations(
|
||||
currentLabel.value,
|
||||
messageAdapter.itemCount,
|
||||
PAGE_SIZE
|
||||
PAGE_SIZE,
|
||||
context?.preferences?.separateIdentities == true
|
||||
)
|
||||
conversationIds.forEach { conversationId ->
|
||||
val conversation = conversationService.getConversation(conversationId)
|
||||
@ -139,6 +144,8 @@ class ConversationListFragment : Fragment(), ListHolder<Label> {
|
||||
super.onPause()
|
||||
}
|
||||
|
||||
override fun reloadList() = doUpdateList(currentLabel.value)
|
||||
|
||||
private fun doUpdateList(label: Label?) {
|
||||
val mainActivity = activity as? MainActivity
|
||||
swipeableConversationAdapter?.clear(label)
|
||||
@ -148,6 +155,9 @@ class ConversationListFragment : Fragment(), ListHolder<Label> {
|
||||
return
|
||||
}
|
||||
emptyTrashMenuItem?.isVisible = label.type == Label.Type.TRASH
|
||||
// I'm not yet sure if it's a good idea in conversation views, so it's off for now
|
||||
deleteAllMenuItem?.isVisible = false
|
||||
|
||||
mainActivity?.apply {
|
||||
if ("archive" == label.toString()) {
|
||||
updateTitle(getString(R.string.archive))
|
||||
@ -298,6 +308,7 @@ class ConversationListFragment : Fragment(), ListHolder<Label> {
|
||||
override fun onCreateOptionsMenu(menu: Menu, inflater: MenuInflater) {
|
||||
inflater.inflate(R.menu.message_list, menu)
|
||||
emptyTrashMenuItem = menu.findItem(R.id.empty_trash)
|
||||
deleteAllMenuItem = menu.findItem(R.id.delete_all)
|
||||
super.onCreateOptionsMenu(menu, inflater)
|
||||
}
|
||||
|
||||
@ -307,13 +318,21 @@ class ConversationListFragment : Fragment(), ListHolder<Label> {
|
||||
currentLabel.value?.let { label ->
|
||||
if (label.type != Label.Type.TRASH) return true
|
||||
|
||||
doAsync {
|
||||
for (message in messageRepo.findMessages(label)) {
|
||||
messageRepo.remove(message)
|
||||
deleteAllMessages(label)
|
||||
}
|
||||
return true
|
||||
}
|
||||
R.id.delete_all -> {
|
||||
currentLabel.value?.let { label ->
|
||||
alert(
|
||||
title = R.string.delete_all_messages_in_list,
|
||||
message = R.string.delete_all_messages_in_list_ask
|
||||
) {
|
||||
positiveButton(R.string.delete) {
|
||||
deleteAllMessages(label)
|
||||
}
|
||||
|
||||
uiThread { doUpdateList(label) }
|
||||
}
|
||||
cancelButton { }
|
||||
}.show()
|
||||
}
|
||||
return true
|
||||
}
|
||||
@ -321,6 +340,16 @@ class ConversationListFragment : Fragment(), ListHolder<Label> {
|
||||
}
|
||||
}
|
||||
|
||||
private fun deleteAllMessages(label: Label) {
|
||||
doAsync {
|
||||
for (message in messageRepo.findMessages(label, 0, 0, context?.preferences?.separateIdentities == true)) {
|
||||
messageRepo.remove(message)
|
||||
}
|
||||
|
||||
uiThread { doUpdateList(label) }
|
||||
}
|
||||
}
|
||||
|
||||
override fun updateList(label: Label) {
|
||||
currentLabel.value = label
|
||||
}
|
||||
|
@ -20,6 +20,8 @@ package ch.dissem.apps.abit
|
||||
* @author Christian Basler
|
||||
*/
|
||||
interface ListHolder<in L> {
|
||||
fun reloadList()
|
||||
|
||||
fun updateList(label: L)
|
||||
|
||||
fun setActivateOnItemClick(activateOnItemClick: Boolean)
|
||||
|
@ -29,6 +29,7 @@ import ch.dissem.apps.abit.drawer.ProfileImageListener
|
||||
import ch.dissem.apps.abit.drawer.ProfileSelectionListener
|
||||
import ch.dissem.apps.abit.listener.ListSelectionListener
|
||||
import ch.dissem.apps.abit.repository.AndroidLabelRepository.Companion.LABEL_ARCHIVE
|
||||
import ch.dissem.apps.abit.repository.AndroidMessageRepository
|
||||
import ch.dissem.apps.abit.service.Singleton
|
||||
import ch.dissem.apps.abit.service.Singleton.currentLabel
|
||||
import ch.dissem.apps.abit.util.*
|
||||
@ -92,6 +93,7 @@ class MainActivity : AppCompatActivity(), ListSelectionListener<Serializable> {
|
||||
private set
|
||||
|
||||
private lateinit var bmc: BitmessageContext
|
||||
private lateinit var messageRepo: AndroidMessageRepository
|
||||
private lateinit var accountHeader: AccountHeader
|
||||
|
||||
private lateinit var drawer: Drawer
|
||||
@ -104,6 +106,7 @@ class MainActivity : AppCompatActivity(), ListSelectionListener<Serializable> {
|
||||
super.onCreate(savedInstanceState)
|
||||
instance = WeakReference(this)
|
||||
bmc = Singleton.getBitmessageContext(this)
|
||||
messageRepo = Singleton.getMessageRepository(this)
|
||||
|
||||
setContentView(R.layout.activity_main)
|
||||
fab.hide()
|
||||
@ -299,8 +302,8 @@ class MainActivity : AppCompatActivity(), ListSelectionListener<Serializable> {
|
||||
for (label in labels) {
|
||||
addLabelEntry(label)
|
||||
}
|
||||
currentLabel.value?.let {
|
||||
drawer.setSelection(it.id as Long)
|
||||
currentLabel.value?.let { label ->
|
||||
drawer.setSelection(label.id as Long)
|
||||
}
|
||||
updateUnread()
|
||||
}
|
||||
@ -334,7 +337,7 @@ class MainActivity : AppCompatActivity(), ListSelectionListener<Serializable> {
|
||||
when (item.name.textRes) {
|
||||
R.string.contacts_and_subscriptions -> {
|
||||
if (itemList is AddressListFragment) {
|
||||
itemList.updateList()
|
||||
itemList.reloadList()
|
||||
} else {
|
||||
changeList(AddressListFragment())
|
||||
}
|
||||
@ -432,7 +435,7 @@ class MainActivity : AppCompatActivity(), ListSelectionListener<Serializable> {
|
||||
if (item.tag is Label) {
|
||||
val label = item.tag as Label
|
||||
if (label !== LABEL_ARCHIVE) {
|
||||
val unread = bmc.messages.countUnread(label)
|
||||
val unread = messageRepo.countUnread(label, preferences.separateIdentities)
|
||||
if (unread > 0) {
|
||||
(item as PrimaryDrawerItem).withBadge(unread.toString())
|
||||
} else {
|
||||
|
@ -33,6 +33,7 @@ import ch.dissem.apps.abit.listener.ListSelectionListener
|
||||
import ch.dissem.apps.abit.repository.AndroidMessageRepository
|
||||
import ch.dissem.apps.abit.service.Singleton
|
||||
import ch.dissem.apps.abit.service.Singleton.currentLabel
|
||||
import ch.dissem.apps.abit.util.preferences
|
||||
import ch.dissem.bitmessage.entity.Plaintext
|
||||
import ch.dissem.bitmessage.entity.valueobject.Label
|
||||
import com.h6ah4i.android.widget.advrecyclerview.animator.SwipeDismissItemAnimator
|
||||
@ -42,9 +43,9 @@ import com.h6ah4i.android.widget.advrecyclerview.touchguard.RecyclerViewTouchAct
|
||||
import com.h6ah4i.android.widget.advrecyclerview.utils.WrapperAdapterUtils
|
||||
import io.github.kobakei.materialfabspeeddial.FabSpeedDialMenu
|
||||
import kotlinx.android.synthetic.main.fragment_message_list.*
|
||||
import org.jetbrains.anko.doAsync
|
||||
import org.jetbrains.anko.*
|
||||
import org.jetbrains.anko.support.v4.alert
|
||||
import org.jetbrains.anko.support.v4.onUiThread
|
||||
import org.jetbrains.anko.uiThread
|
||||
import java.util.*
|
||||
|
||||
private const val PAGE_SIZE = 15
|
||||
@ -89,6 +90,7 @@ class MessageListFragment : Fragment(), ListHolder<Label> {
|
||||
}
|
||||
|
||||
private var emptyTrashMenuItem: MenuItem? = null
|
||||
private var deleteAllMenuItem: MenuItem? = null
|
||||
private lateinit var messageRepo: AndroidMessageRepository
|
||||
private var activateOnItemClick: Boolean = false
|
||||
|
||||
@ -98,10 +100,12 @@ class MessageListFragment : Fragment(), ListHolder<Label> {
|
||||
isLoading = true
|
||||
swipeableMessageAdapter?.let { messageAdapter ->
|
||||
doAsync {
|
||||
val label = currentLabel.value
|
||||
val messages = messageRepo.findMessages(
|
||||
currentLabel.value,
|
||||
label,
|
||||
messageAdapter.itemCount,
|
||||
PAGE_SIZE
|
||||
PAGE_SIZE,
|
||||
context?.preferences?.separateIdentities == true && label?.type != Label.Type.BROADCAST
|
||||
)
|
||||
onUiThread {
|
||||
messageAdapter.addAll(messages)
|
||||
@ -133,6 +137,8 @@ class MessageListFragment : Fragment(), ListHolder<Label> {
|
||||
super.onPause()
|
||||
}
|
||||
|
||||
override fun reloadList() = doUpdateList(currentLabel.value)
|
||||
|
||||
private fun doUpdateList(label: Label?) {
|
||||
// If the menu item isn't available yet, we should wait - the method will be called again once it's
|
||||
// initialized.
|
||||
@ -155,6 +161,7 @@ class MessageListFragment : Fragment(), ListHolder<Label> {
|
||||
|
||||
loadMoreItems()
|
||||
}
|
||||
deleteAllMenuItem?.isVisible = label?.type != Label.Type.TRASH
|
||||
}
|
||||
|
||||
override fun onCreateView(
|
||||
@ -300,6 +307,7 @@ class MessageListFragment : Fragment(), ListHolder<Label> {
|
||||
override fun onCreateOptionsMenu(menu: Menu, inflater: MenuInflater) {
|
||||
inflater.inflate(R.menu.message_list, menu)
|
||||
emptyTrashMenuItem = menu.findItem(R.id.empty_trash)
|
||||
deleteAllMenuItem = menu.findItem(R.id.delete_all)
|
||||
currentLabel.value?.let { doUpdateList(it) }
|
||||
super.onCreateOptionsMenu(menu, inflater)
|
||||
}
|
||||
@ -310,13 +318,21 @@ class MessageListFragment : Fragment(), ListHolder<Label> {
|
||||
currentLabel.value?.let { label ->
|
||||
if (label.type != Label.Type.TRASH) return true
|
||||
|
||||
doAsync {
|
||||
for (message in messageRepo.findMessages(label)) {
|
||||
messageRepo.remove(message)
|
||||
deleteAllMessages(label)
|
||||
}
|
||||
return true
|
||||
}
|
||||
R.id.delete_all -> {
|
||||
currentLabel.value?.let { label ->
|
||||
alert(
|
||||
title = R.string.delete_all_messages_in_list,
|
||||
message = R.string.delete_all_messages_in_list_ask
|
||||
) {
|
||||
positiveButton(R.string.delete) {
|
||||
deleteAllMessages(label)
|
||||
}
|
||||
|
||||
uiThread { doUpdateList(label) }
|
||||
}
|
||||
cancelButton { }
|
||||
}.show()
|
||||
}
|
||||
return true
|
||||
}
|
||||
@ -324,6 +340,16 @@ class MessageListFragment : Fragment(), ListHolder<Label> {
|
||||
}
|
||||
}
|
||||
|
||||
private fun deleteAllMessages(label: Label) {
|
||||
doAsync {
|
||||
for (message in messageRepo.findMessages(label, 0, 0, context?.preferences?.separateIdentities == true)) {
|
||||
messageRepo.remove(message)
|
||||
}
|
||||
|
||||
uiThread { doUpdateList(label) }
|
||||
}
|
||||
}
|
||||
|
||||
override fun updateList(label: Label) {
|
||||
currentLabel.value = label
|
||||
}
|
||||
|
@ -21,8 +21,8 @@ import ch.dissem.bitmessage.entity.BitmessageAddress
|
||||
import android.widget.Toast.LENGTH_LONG
|
||||
|
||||
class ProfileSelectionListener(
|
||||
private val ctx: Context,
|
||||
private val fragmentManager: FragmentManager
|
||||
private val ctx: Context,
|
||||
private val fragmentManager: FragmentManager
|
||||
) : AccountHeader.OnAccountHeaderListener {
|
||||
|
||||
override fun onProfileChanged(view: View, profile: IProfile<*>, current: Boolean): Boolean {
|
||||
@ -42,6 +42,13 @@ class ProfileSelectionListener(
|
||||
val tag = profile.tag
|
||||
if (tag is BitmessageAddress) {
|
||||
Singleton.setIdentity(tag)
|
||||
MainActivity.apply {
|
||||
updateUnread()
|
||||
val itemList = supportFragmentManager.findFragmentById(R.id.item_list)
|
||||
if (itemList is ListHolder<*>) {
|
||||
itemList.reloadList()
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -21,6 +21,7 @@ import android.database.Cursor
|
||||
import android.database.DatabaseUtils
|
||||
import android.database.sqlite.SQLiteDatabase
|
||||
import ch.dissem.apps.abit.repository.AndroidLabelRepository.Companion.LABEL_ARCHIVE
|
||||
import ch.dissem.apps.abit.util.Preferences
|
||||
import ch.dissem.apps.abit.util.UuidUtils
|
||||
import ch.dissem.apps.abit.util.UuidUtils.asUuid
|
||||
import ch.dissem.bitmessage.entity.BitmessageAddress
|
||||
@ -38,7 +39,14 @@ import java.util.*
|
||||
/**
|
||||
* [MessageRepository] implementation using the Android SQL API.
|
||||
*/
|
||||
class AndroidMessageRepository(private val sql: SqlHelper) : AbstractMessageRepository() {
|
||||
class AndroidMessageRepository(private val sql: SqlHelper, private val prefs: Preferences) : AbstractMessageRepository() {
|
||||
|
||||
fun findMessages(label: Label?, offset: Int, limit: Int, separateIdentities: Boolean) =
|
||||
if (label === LABEL_ARCHIVE || label === null) {
|
||||
find("id NOT IN (SELECT message_id FROM Message_Label)", offset, limit, separateIdentities)
|
||||
} else {
|
||||
find("id IN (SELECT message_id FROM Message_Label WHERE label_id=" + label.id + ")", offset, limit, separateIdentities)
|
||||
}
|
||||
|
||||
override fun findMessages(label: Label?, offset: Int, limit: Int) =
|
||||
if (label === LABEL_ARCHIVE) {
|
||||
@ -54,30 +62,56 @@ class AndroidMessageRepository(private val sql: SqlHelper) : AbstractMessageRepo
|
||||
null
|
||||
).toInt()
|
||||
|
||||
override fun countUnread(label: Label?) = when {
|
||||
label === LABEL_ARCHIVE -> 0
|
||||
label == null -> DatabaseUtils.queryNumEntries(
|
||||
sql.readableDatabase,
|
||||
TABLE_NAME,
|
||||
"id IN (SELECT message_id FROM Message_Label WHERE label_id IN (SELECT id FROM Label WHERE type=?))",
|
||||
arrayOf(Label.Type.UNREAD.name)
|
||||
).toInt()
|
||||
else -> DatabaseUtils.queryNumEntries(
|
||||
sql.readableDatabase,
|
||||
TABLE_NAME,
|
||||
" id IN (SELECT message_id FROM Message_Label WHERE label_id=?) " +
|
||||
"AND id IN (SELECT message_id FROM Message_Label WHERE label_id IN (SELECT id FROM Label WHERE type=?))",
|
||||
arrayOf(label.id.toString(), Label.Type.UNREAD.name)
|
||||
).toInt()
|
||||
private fun getSelectIdentity(separateIdentities: Boolean): Pair<String, Array<String>> {
|
||||
if (separateIdentities) {
|
||||
val identity = prefs.currentIdentity
|
||||
return if (prefs.separateIdentities && identity != null) {
|
||||
"AND (type = 'BROADCAST' OR recipient=? OR sender=?)" to arrayOf(identity.address, identity.address)
|
||||
} else {
|
||||
"" to emptyArray()
|
||||
}
|
||||
} else {
|
||||
return "" to emptyArray()
|
||||
}
|
||||
}
|
||||
|
||||
override fun findConversations(label: Label?, offset: Int, limit: Int): List<UUID> {
|
||||
override fun countUnread(label: Label?) = countUnread(label, false)
|
||||
|
||||
fun countUnread(label: Label?, separateIdentities: Boolean) = getSelectIdentity(separateIdentities).let { (selectIdentityQuery, selectIdentityArgs) ->
|
||||
when {
|
||||
label === LABEL_ARCHIVE -> 0
|
||||
label == null -> DatabaseUtils.queryNumEntries(
|
||||
sql.readableDatabase,
|
||||
TABLE_NAME,
|
||||
"id IN (SELECT message_id FROM Message_Label WHERE label_id IN (SELECT id FROM Label WHERE type=?)) " +
|
||||
selectIdentityQuery,
|
||||
arrayOf(Label.Type.UNREAD.name, *selectIdentityArgs)
|
||||
).toInt()
|
||||
else -> DatabaseUtils.queryNumEntries(
|
||||
sql.readableDatabase,
|
||||
TABLE_NAME,
|
||||
"id IN (SELECT message_id FROM Message_Label WHERE label_id=?) " +
|
||||
"AND id IN (SELECT message_id FROM Message_Label WHERE label_id IN (SELECT id FROM Label WHERE type=?)) " +
|
||||
selectIdentityQuery,
|
||||
arrayOf(label.id.toString(), Label.Type.UNREAD.name, *selectIdentityArgs)
|
||||
).toInt()
|
||||
}
|
||||
}
|
||||
|
||||
override fun findConversations(label: Label?, offset: Int, limit: Int): List<UUID> = findConversations(label, offset, limit, false)
|
||||
|
||||
fun findConversations(label: Label?, offset: Int, limit: Int, separateIdentities: Boolean): List<UUID> {
|
||||
val projection = arrayOf(COLUMN_CONVERSATION)
|
||||
val (selectIdentityQuery, selectIdentityArgs) = getSelectIdentity(separateIdentities)
|
||||
|
||||
val where = when {
|
||||
label === LABEL_ARCHIVE -> "id NOT IN (SELECT message_id FROM Message_Label)"
|
||||
label == null -> null
|
||||
else -> "id IN (SELECT message_id FROM Message_Label WHERE label_id=${label.id})"
|
||||
label === LABEL_ARCHIVE -> "id NOT IN (SELECT message_id FROM Message_Label) $selectIdentityQuery"
|
||||
label == null -> if (selectIdentityQuery.isNotBlank()) {
|
||||
"type = 'BROADCAST' OR recipient=? OR sender=?"
|
||||
} else {
|
||||
null
|
||||
}
|
||||
else -> "id IN (SELECT message_id FROM Message_Label WHERE label_id=${label.id}) $selectIdentityQuery"
|
||||
}
|
||||
val result = LinkedList<UUID>()
|
||||
sql.readableDatabase.query(
|
||||
@ -85,7 +119,7 @@ class AndroidMessageRepository(private val sql: SqlHelper) : AbstractMessageRepo
|
||||
TABLE_NAME,
|
||||
projection,
|
||||
where,
|
||||
null, null, null,
|
||||
selectIdentityArgs, null, null,
|
||||
"$COLUMN_RECEIVED DESC, $COLUMN_SENT DESC",
|
||||
if (limit == 0) null else "$offset, $limit"
|
||||
).use { c ->
|
||||
@ -140,8 +174,11 @@ class AndroidMessageRepository(private val sql: SqlHelper) : AbstractMessageRepo
|
||||
db.update(PARENTS_TABLE_NAME, values, where, null)
|
||||
}
|
||||
|
||||
override fun find(where: String, offset: Int, limit: Int): List<Plaintext> {
|
||||
override fun find(where: String, offset: Int, limit: Int) = find(where, offset, limit, false)
|
||||
|
||||
fun find(where: String, offset: Int, limit: Int, separateIdentities: Boolean): List<Plaintext> {
|
||||
val result = LinkedList<Plaintext>()
|
||||
val (selectIdentityQuery, selectIdentityArgs) = getSelectIdentity(separateIdentities)
|
||||
|
||||
// Define a projection that specifies which columns from the database
|
||||
// you will actually use after this query.
|
||||
@ -164,7 +201,7 @@ class AndroidMessageRepository(private val sql: SqlHelper) : AbstractMessageRepo
|
||||
|
||||
sql.readableDatabase.query(
|
||||
TABLE_NAME, projection,
|
||||
where, null, null, null,
|
||||
"$where $selectIdentityQuery", selectIdentityArgs, null, null,
|
||||
"$COLUMN_RECEIVED DESC, $COLUMN_SENT DESC",
|
||||
if (limit == 0) null else "$offset, $limit"
|
||||
).use { c ->
|
||||
@ -318,4 +355,5 @@ class AndroidMessageRepository(private val sql: SqlHelper) : AbstractMessageRepo
|
||||
private const val JT_COLUMN_MESSAGE = "message_id"
|
||||
private const val JT_COLUMN_LABEL = "label_id"
|
||||
}
|
||||
|
||||
}
|
||||
|
@ -64,7 +64,7 @@ object Singleton {
|
||||
// work-around for messages that are deleted from unread, which already have the unread label removed
|
||||
swipeableMessageAdapter.remove(message)
|
||||
}
|
||||
label == AndroidLabelRepository.LABEL_ARCHIVE && !added.isEmpty() -> {
|
||||
label == AndroidLabelRepository.LABEL_ARCHIVE && !added.isEmpty() -> {
|
||||
// work-around for messages in archive, which isn't an actual label but an absence of labels
|
||||
swipeableMessageAdapter.remove(message)
|
||||
}
|
||||
@ -110,12 +110,13 @@ object Singleton {
|
||||
inventory = AndroidInventory(sqlHelper)
|
||||
addressRepo = AndroidAddressRepository(sqlHelper)
|
||||
labelRepo = AndroidLabelRepository(sqlHelper, ctx)
|
||||
messageRepo = AndroidMessageRepository(sqlHelper)
|
||||
messageRepo = AndroidMessageRepository(sqlHelper, ctx.preferences)
|
||||
proofOfWorkRepo = AndroidProofOfWorkRepository(sqlHelper).also { powRepo = it }
|
||||
networkHandler = NioNetworkHandler(4)
|
||||
listener = getMessageListener(ctx)
|
||||
labeler = Singleton.labeler
|
||||
preferences.sendPubkeyOnIdentityCreation = false
|
||||
preferences.port = context.preferences.listeningPort
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -29,6 +29,7 @@ object Constants {
|
||||
const val PREFERENCE_REQUEST_ACK = "request_acknowledgments"
|
||||
const val PREFERENCE_POW_AVERAGE = "average_pow_time_ms"
|
||||
const val PREFERENCE_POW_COUNT = "pow_count"
|
||||
const val PREFERENCE_SEPARATE_IDENTITIES = "separate_identities"
|
||||
|
||||
const val BITMESSAGE_URL_SCHEMA = "bitmessage:"
|
||||
|
||||
|
@ -21,10 +21,12 @@ import android.content.Intent
|
||||
import android.content.IntentFilter
|
||||
import android.os.BatteryManager
|
||||
import android.os.Build
|
||||
import ch.dissem.apps.abit.service.Singleton
|
||||
import ch.dissem.apps.abit.util.Constants.PREFERENCE_EMULATE_CONVERSATIONS
|
||||
import ch.dissem.apps.abit.util.Constants.PREFERENCE_ONLINE
|
||||
import ch.dissem.apps.abit.util.Constants.PREFERENCE_REQUEST_ACK
|
||||
import ch.dissem.apps.abit.util.Constants.PREFERENCE_REQUIRE_CHARGING
|
||||
import ch.dissem.apps.abit.util.Constants.PREFERENCE_SEPARATE_IDENTITIES
|
||||
import ch.dissem.apps.abit.util.Constants.PREFERENCE_WIFI_ONLY
|
||||
import org.jetbrains.anko.batteryManager
|
||||
import org.jetbrains.anko.connectivityManager
|
||||
@ -48,6 +50,8 @@ class Preferences internal constructor(private val ctx: Context) {
|
||||
|
||||
private val isAllowedForCharging get() = !requireCharging || isCharging
|
||||
|
||||
private val sharedPreferences = ctx.defaultSharedPreferences
|
||||
|
||||
private val isCharging
|
||||
get() = if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) {
|
||||
ctx.batteryManager.isCharging
|
||||
@ -58,20 +62,20 @@ class Preferences internal constructor(private val ctx: Context) {
|
||||
}
|
||||
|
||||
var wifiOnly
|
||||
get() = ctx.defaultSharedPreferences.getBoolean(PREFERENCE_WIFI_ONLY, true)
|
||||
get() = sharedPreferences.getBoolean(PREFERENCE_WIFI_ONLY, true)
|
||||
set(value) {
|
||||
ctx.defaultSharedPreferences.edit()
|
||||
sharedPreferences.edit()
|
||||
.putBoolean(PREFERENCE_WIFI_ONLY, value)
|
||||
.apply()
|
||||
}
|
||||
|
||||
val requireCharging get() = ctx.defaultSharedPreferences.getBoolean(PREFERENCE_REQUIRE_CHARGING, true)
|
||||
val requireCharging get() = sharedPreferences.getBoolean(PREFERENCE_REQUIRE_CHARGING, true)
|
||||
|
||||
val emulateConversations get() = ctx.defaultSharedPreferences.getBoolean(PREFERENCE_EMULATE_CONVERSATIONS, true)
|
||||
val emulateConversations get() = sharedPreferences.getBoolean(PREFERENCE_EMULATE_CONVERSATIONS, true)
|
||||
|
||||
val exportDirectory by lazy { File(ctx.filesDir, "exports") }
|
||||
|
||||
val requestAcknowledgements = ctx.defaultSharedPreferences.getBoolean(PREFERENCE_REQUEST_ACK, true)
|
||||
val requestAcknowledgements = sharedPreferences.getBoolean(PREFERENCE_REQUEST_ACK, true)
|
||||
|
||||
fun cleanupExportDirectory() {
|
||||
if (exportDirectory.exists()) {
|
||||
@ -88,9 +92,9 @@ class Preferences internal constructor(private val ctx: Context) {
|
||||
}
|
||||
|
||||
var online
|
||||
get() = ctx.defaultSharedPreferences.getBoolean(PREFERENCE_ONLINE, true)
|
||||
get() = sharedPreferences.getBoolean(PREFERENCE_ONLINE, true)
|
||||
set(value) {
|
||||
ctx.defaultSharedPreferences.edit()
|
||||
sharedPreferences.edit()
|
||||
.putBoolean(PREFERENCE_ONLINE, value)
|
||||
.apply()
|
||||
if (value) {
|
||||
@ -100,6 +104,16 @@ class Preferences internal constructor(private val ctx: Context) {
|
||||
}
|
||||
}
|
||||
|
||||
val separateIdentities
|
||||
get() = sharedPreferences.getBoolean(PREFERENCE_SEPARATE_IDENTITIES, false)
|
||||
|
||||
val currentIdentity
|
||||
get() = Singleton.getIdentity(ctx)
|
||||
|
||||
val listeningPort
|
||||
get() = sharedPreferences.getString("listening_port", null)?.toIntOrNull()
|
||||
?: 8444
|
||||
|
||||
companion object {
|
||||
private var instance: WeakReference<Preferences>? = null
|
||||
|
||||
|
@ -1,11 +1,18 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
|
||||
<menu xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
xmlns:app="http://schemas.android.com/apk/res-auto">
|
||||
xmlns:app="http://schemas.android.com/apk/res-auto">
|
||||
<item
|
||||
android:id="@+id/empty_trash"
|
||||
app:showAsAction="never"
|
||||
android:icon="@drawable/ic_action_delete"
|
||||
android:title="@string/empty_trash"
|
||||
android:visible="false"/>
|
||||
</menu>
|
||||
android:id="@+id/empty_trash"
|
||||
android:icon="@drawable/ic_action_delete"
|
||||
android:title="@string/empty_trash"
|
||||
android:visible="false"
|
||||
app:showAsAction="never" />
|
||||
<item
|
||||
android:id="@+id/delete_all"
|
||||
android:icon="@drawable/ic_action_delete"
|
||||
android:title="@string/delete_all_messages_in_list"
|
||||
android:visible="true"
|
||||
app:showAsAction="never" />
|
||||
|
||||
</menu>
|
||||
|
@ -145,4 +145,5 @@ Als Alternative kann in den Einstellungen ein vertrauenswürdiger Knoten konfigu
|
||||
<string name="preference_group_user_experience">Verhalten</string>
|
||||
<string name="preference_group_user_experience_summary">Ändern, wie Nachrichten dargestellt werden</string>
|
||||
<string name="bitmessage_service_description">Hält die Verbindung zum Bitmessage-Netzwerk.</string>
|
||||
<string name="preference_port">Port</string>
|
||||
</resources>
|
||||
|
@ -156,4 +156,10 @@ As an alternative you could configure a trusted node in the settings, but as of
|
||||
<string name="online">Online</string>
|
||||
<string name="warning_low_memory">Low memory!</string>
|
||||
<string name="bitmessage_service_description">Keeps the connection to the bitmessage network.</string>
|
||||
<string name="preference_port">Port</string>
|
||||
<string name="preference_port_summary">Listen on this port for incoming connections. You might need to shortly go offline before the new port is used.</string>
|
||||
<string name="preference_separate_identities_summary">Show messages for selected identity only</string>
|
||||
<string name="preference_separate_identities">Filter messages by identity</string>
|
||||
<string name="delete_all_messages_in_list">Delete all</string>
|
||||
<string name="delete_all_messages_in_list_ask">Delete all messages in list?</string>
|
||||
</resources>
|
||||
|
@ -3,10 +3,15 @@
|
||||
|
||||
<PreferenceScreen
|
||||
android:key="preference_ux"
|
||||
android:title="@string/preference_group_user_experience"
|
||||
android:persistent="false"
|
||||
android:summary="@string/preference_group_user_experience_summary"
|
||||
android:persistent="false">
|
||||
android:title="@string/preference_group_user_experience">
|
||||
|
||||
<SwitchPreferenceCompat
|
||||
android:defaultValue="false"
|
||||
android:key="separate_identities"
|
||||
android:summary="@string/preference_separate_identities_summary"
|
||||
android:title="@string/preference_separate_identities" />
|
||||
<SwitchPreferenceCompat
|
||||
android:defaultValue="true"
|
||||
android:key="emulate_conversations"
|
||||
@ -22,9 +27,9 @@
|
||||
|
||||
<PreferenceScreen
|
||||
android:key="preference_network_and_performance"
|
||||
android:title="@string/preference_group_network_and_performance"
|
||||
android:persistent="false"
|
||||
android:summary="@string/preference_group_network_and_performance_summary"
|
||||
android:persistent="false">
|
||||
android:title="@string/preference_group_network_and_performance">
|
||||
|
||||
<SwitchPreferenceCompat
|
||||
android:defaultValue="true"
|
||||
@ -46,9 +51,9 @@
|
||||
|
||||
<PreferenceScreen
|
||||
android:key="preference_advanced"
|
||||
android:title="@string/preference_group_advanced"
|
||||
android:persistent="false"
|
||||
android:summary="@string/preference_group_advanced_summary"
|
||||
android:persistent="false">
|
||||
android:title="@string/preference_group_advanced">
|
||||
|
||||
<Preference
|
||||
android:key="cleanup"
|
||||
@ -68,6 +73,13 @@
|
||||
android:summary="@string/status_summary"
|
||||
android:title="@string/status" />
|
||||
|
||||
<EditTextPreference
|
||||
android:defaultValue="8444"
|
||||
android:key="listening_port"
|
||||
android:summary="@string/preference_port_summary"
|
||||
android:title="@string/preference_port"
|
||||
android:numeric="integer"/>
|
||||
|
||||
</PreferenceScreen>
|
||||
|
||||
<Preference
|
||||
|
Loading…
Reference in New Issue
Block a user