Add message grouping by subject

This commit is contained in:
Christian Basler 2018-04-03 22:14:46 +02:00
parent 6a311a0346
commit 1426b786e8
7 changed files with 67 additions and 36 deletions

View File

@ -114,7 +114,7 @@ class MainActivity : AppCompatActivity(), ListSelectionListener<Serializable> {
val toolbar = findViewById<Toolbar>(R.id.toolbar)
setSupportActionBar(toolbar)
val listFragment = MessageListFragment()
val listFragment = ConversationListFragment()
supportFragmentManager
.beginTransaction()
.replace(R.id.item_list, listFragment)
@ -303,6 +303,7 @@ class MainActivity : AppCompatActivity(), ListSelectionListener<Serializable> {
currentLabel.value = intent.getSerializableExtra(EXTRA_SHOW_LABEL) as Label
} else if (currentLabel.value == null) {
currentLabel.value = labels[0]
}
for (label in labels) {
addLabelEntry(label)

View File

@ -19,8 +19,11 @@ package ch.dissem.apps.abit.listener
import android.content.Context
import ch.dissem.apps.abit.MainActivity
import ch.dissem.apps.abit.notification.NewMessageNotification
import ch.dissem.apps.abit.util.Preferences
import ch.dissem.bitmessage.BitmessageContext
import ch.dissem.bitmessage.entity.Plaintext
import ch.dissem.bitmessage.ports.MessageRepository
import ch.dissem.bitmessage.utils.ConversationService
import java.util.*
import java.util.concurrent.Executors
@ -33,14 +36,26 @@ import java.util.concurrent.Executors
* notifications should be combined.
*
*/
class MessageListener(ctx: Context) : BitmessageContext.Listener {
class MessageListener(ctx: Context) : BitmessageContext.Listener.WithContext {
override fun setContext(ctx: BitmessageContext) {
messageRepo = ctx.messages
conversationService = ConversationService(messageRepo)
}
private val unacknowledged = LinkedList<Plaintext>()
private var numberOfUnacknowledgedMessages = 0
private val notification = NewMessageNotification(ctx)
private val pool = Executors.newSingleThreadExecutor()
private lateinit var messageRepo: MessageRepository
private lateinit var conversationService: ConversationService
init {
emulateConversations = Preferences.isEmulateConversations(ctx)
}
override fun receive(plaintext: Plaintext) {
pool.submit {
updateConversation(plaintext)
unacknowledged.addFirst(plaintext)
numberOfUnacknowledgedMessages++
if (unacknowledged.size > 5) {
@ -65,4 +80,17 @@ class MessageListener(ctx: Context) : BitmessageContext.Listener {
numberOfUnacknowledgedMessages = 0
}
}
fun updateConversation(plaintext: Plaintext) {
if (emulateConversations && plaintext.encoding != Plaintext.Encoding.EXTENDED) {
conversationService.getSubject(listOf(plaintext))?.let { subject ->
plaintext.conversationId = UUID.nameUUIDFromBytes(subject.toByteArray())
messageRepo.save(plaintext)
}
}
}
companion object {
private var emulateConversations = false
}
}

View File

@ -23,6 +23,7 @@ import java.util.regex.Pattern
*/
object Constants {
const val PREFERENCE_WIFI_ONLY = "wifi_only"
const val PREFERENCE_EMULATE_CONVERSATIONS = "emulate_conversations"
const val PREFERENCE_TRUSTED_NODE = "trusted_node"
const val PREFERENCE_SYNC_TIMEOUT = "sync_timeout"
const val PREFERENCE_SERVER_POW = "server_pow"

View File

@ -17,15 +17,16 @@
package ch.dissem.apps.abit.util
import android.content.Context
import android.preference.PreferenceManager
import ch.dissem.apps.abit.R
import ch.dissem.apps.abit.notification.ErrorNotification
import ch.dissem.apps.abit.util.Constants.PREFERENCE_EMULATE_CONVERSATIONS
import ch.dissem.apps.abit.util.Constants.PREFERENCE_FULL_NODE
import ch.dissem.apps.abit.util.Constants.PREFERENCE_REQUEST_ACK
import ch.dissem.apps.abit.util.Constants.PREFERENCE_SYNC_TIMEOUT
import ch.dissem.apps.abit.util.Constants.PREFERENCE_TRUSTED_NODE
import ch.dissem.apps.abit.util.Constants.PREFERENCE_WIFI_ONLY
import org.jetbrains.anko.connectivityManager
import org.jetbrains.anko.defaultSharedPreferences
import org.slf4j.LoggerFactory
import java.io.File
import java.io.IOException
@ -77,50 +78,41 @@ object Preferences {
return 8444
}
fun getTimeoutInSeconds(ctx: Context): Long {
val preference = getPreference(ctx, PREFERENCE_SYNC_TIMEOUT) ?: return 120
return preference.toLong()
}
fun getTimeoutInSeconds(ctx: Context): Long =
getPreference(ctx, PREFERENCE_SYNC_TIMEOUT)?.toLong() ?: 120
private fun getPreference(ctx: Context, name: String): String? {
val preferences = PreferenceManager.getDefaultSharedPreferences(ctx)
private fun getPreference(ctx: Context, name: String): String? =
ctx.defaultSharedPreferences.getString(name, null)
return preferences.getString(name, null)
}
fun isConnectionAllowed(ctx: Context) =
!isWifiOnly(ctx) || !ctx.connectivityManager.isActiveNetworkMetered
fun isConnectionAllowed(ctx: Context) = !isWifiOnly(ctx) || !ctx.connectivityManager.isActiveNetworkMetered
fun isWifiOnly(ctx: Context): Boolean {
val preferences = PreferenceManager.getDefaultSharedPreferences(ctx)
return preferences.getBoolean(PREFERENCE_WIFI_ONLY, true)
}
fun isWifiOnly(ctx: Context) =
ctx.defaultSharedPreferences.getBoolean(PREFERENCE_WIFI_ONLY, true)
fun setWifiOnly(ctx: Context, status: Boolean) {
val preferences = PreferenceManager.getDefaultSharedPreferences(ctx)
preferences.edit().putBoolean(PREFERENCE_WIFI_ONLY, status).apply()
ctx.defaultSharedPreferences.edit()
.putBoolean(PREFERENCE_WIFI_ONLY, status)
.apply()
}
fun isFullNodeActive(ctx: Context): Boolean {
val preferences = PreferenceManager.getDefaultSharedPreferences(ctx)
return preferences.getBoolean(PREFERENCE_FULL_NODE, false)
}
fun isEmulateConversations(ctx: Context) =
ctx.defaultSharedPreferences.getBoolean(PREFERENCE_EMULATE_CONVERSATIONS, true)
fun isFullNodeActive(ctx: Context) =
ctx.defaultSharedPreferences.getBoolean(PREFERENCE_FULL_NODE, false)
fun setFullNodeActive(ctx: Context, status: Boolean) {
val preferences = PreferenceManager.getDefaultSharedPreferences(ctx)
preferences.edit().putBoolean(PREFERENCE_FULL_NODE, status).apply()
ctx.defaultSharedPreferences.edit()
.putBoolean(PREFERENCE_FULL_NODE, status)
.apply()
}
fun getExportDirectory(ctx: Context) = File(ctx.filesDir, "exports")
fun requestAcknowledgements(ctx: Context): Boolean {
val preferences = PreferenceManager.getDefaultSharedPreferences(ctx)
return preferences.getBoolean(PREFERENCE_REQUEST_ACK, true)
}
fun setRequestAcknowledgements(ctx: Context, status: Boolean) {
val preferences = PreferenceManager.getDefaultSharedPreferences(ctx)
preferences.edit().putBoolean(PREFERENCE_REQUEST_ACK, status).apply()
}
fun requestAcknowledgements(ctx: Context) =
ctx.defaultSharedPreferences.getBoolean(PREFERENCE_REQUEST_ACK, true)
fun cleanupExportDirectory(ctx: Context) {
val exportDirectory = getExportDirectory(ctx)

View File

@ -137,4 +137,6 @@ Als Alternative kann in den Einstellungen ein vertrauenswürdiger Knoten konfigu
<string name="broadcasts">Broadcasts</string>
<string name="encoding_simple">einfach</string>
<string name="encoding_extended">erweitert</string>
<string name="emulate_conversations">Konversation erraten</string>
<string name="emulate_conversations_summary">Benutze Betreff um zu erraten welche Nachrichten zusammengehören. Die Reihenfolge stimmt häufig nicht.</string>
</resources>

View File

@ -137,4 +137,6 @@ As an alternative you could configure a trusted node in the settings, but as of
<string name="encoding_simple">simple</string>
<string name="encoding_extended">extended</string>
<string name="context_menu">actions</string>
<string name="emulate_conversations">Guess conversations</string>
<string name="emulate_conversations_summary">Use subject to determine which messages belong together. The order will likely be wrong.</string>
</resources>

View File

@ -5,6 +5,11 @@
android:key="wifi_only"
android:summary="@string/wifi_only_summary"
android:title="@string/wifi_only" />
<android.support.v7.preference.SwitchPreferenceCompat
android:defaultValue="true"
android:key="emulate_conversations"
android:summary="@string/emulate_conversations_summary"
android:title="@string/emulate_conversations" />
<android.support.v7.preference.SwitchPreferenceCompat
android:defaultValue="true"
android:key="request_acknowledgements"