diff --git a/app/src/main/java/ch/dissem/apps/abit/MainActivity.kt b/app/src/main/java/ch/dissem/apps/abit/MainActivity.kt index 5f7df5f..82fe544 100644 --- a/app/src/main/java/ch/dissem/apps/abit/MainActivity.kt +++ b/app/src/main/java/ch/dissem/apps/abit/MainActivity.kt @@ -114,7 +114,7 @@ class MainActivity : AppCompatActivity(), ListSelectionListener { val toolbar = findViewById(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 { currentLabel.value = intent.getSerializableExtra(EXTRA_SHOW_LABEL) as Label } else if (currentLabel.value == null) { currentLabel.value = labels[0] + } for (label in labels) { addLabelEntry(label) diff --git a/app/src/main/java/ch/dissem/apps/abit/listener/MessageListener.kt b/app/src/main/java/ch/dissem/apps/abit/listener/MessageListener.kt index cb0e4ac..a9405af 100644 --- a/app/src/main/java/ch/dissem/apps/abit/listener/MessageListener.kt +++ b/app/src/main/java/ch/dissem/apps/abit/listener/MessageListener.kt @@ -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() 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 + } } diff --git a/app/src/main/java/ch/dissem/apps/abit/util/Constants.kt b/app/src/main/java/ch/dissem/apps/abit/util/Constants.kt index ffede4f..a57a4b2 100644 --- a/app/src/main/java/ch/dissem/apps/abit/util/Constants.kt +++ b/app/src/main/java/ch/dissem/apps/abit/util/Constants.kt @@ -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" diff --git a/app/src/main/java/ch/dissem/apps/abit/util/Preferences.kt b/app/src/main/java/ch/dissem/apps/abit/util/Preferences.kt index b8b571f..7b75161 100644 --- a/app/src/main/java/ch/dissem/apps/abit/util/Preferences.kt +++ b/app/src/main/java/ch/dissem/apps/abit/util/Preferences.kt @@ -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 @@ -70,57 +71,48 @@ object Preferences { return Integer.parseInt(portString) } catch (e: NumberFormatException) { ErrorNotification(ctx) - .setError(R.string.error_invalid_sync_port, portString) - .show() + .setError(R.string.error_invalid_sync_port, portString) + .show() } } 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) diff --git a/app/src/main/res/values-de/strings.xml b/app/src/main/res/values-de/strings.xml index f71c93c..d300a58 100644 --- a/app/src/main/res/values-de/strings.xml +++ b/app/src/main/res/values-de/strings.xml @@ -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> diff --git a/app/src/main/res/values/strings.xml b/app/src/main/res/values/strings.xml index 007bb84..8cd8186 100644 --- a/app/src/main/res/values/strings.xml +++ b/app/src/main/res/values/strings.xml @@ -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> diff --git a/app/src/main/res/xml/preferences.xml b/app/src/main/res/xml/preferences.xml index d62ac94..0a408e5 100644 --- a/app/src/main/res/xml/preferences.xml +++ b/app/src/main/res/xml/preferences.xml @@ -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"