From 78f9621afad180d50167415e09f034b8c609fa48 Mon Sep 17 00:00:00 2001 From: Christian Basler Date: Fri, 13 Apr 2018 12:39:59 +0200 Subject: [PATCH] =?UTF-8?q?=F0=9F=9A=A7=20Add=20code=20to=20migrate=20exis?= =?UTF-8?q?ting=20conversations?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Work in progress: does work, but usually doesn't finish. This needs to be moved into some proper batch processing. --- .../ch/dissem/apps/abit/SettingsFragment.kt | 51 ++++++++++++++++++- .../repository/AndroidMessageRepository.kt | 33 ++++++++++++ app/src/main/res/values/strings.xml | 1 + app/src/main/res/xml/preferences.xml | 5 ++ 4 files changed, 89 insertions(+), 1 deletion(-) diff --git a/app/src/main/java/ch/dissem/apps/abit/SettingsFragment.kt b/app/src/main/java/ch/dissem/apps/abit/SettingsFragment.kt index 0cc5dca..7378af7 100644 --- a/app/src/main/java/ch/dissem/apps/abit/SettingsFragment.kt +++ b/app/src/main/java/ch/dissem/apps/abit/SettingsFragment.kt @@ -32,12 +32,14 @@ import ch.dissem.apps.abit.util.Constants.PREFERENCE_SERVER_POW import ch.dissem.apps.abit.util.Constants.PREFERENCE_TRUSTED_NODE import ch.dissem.apps.abit.util.Exports import ch.dissem.apps.abit.util.Preferences +import ch.dissem.bitmessage.entity.Plaintext import com.mikepenz.aboutlibraries.Libs import com.mikepenz.aboutlibraries.LibsBuilder import org.jetbrains.anko.doAsync import org.jetbrains.anko.support.v4.indeterminateProgressDialog import org.jetbrains.anko.support.v4.startActivity import org.jetbrains.anko.uiThread +import java.util.* /** * @author Christian Basler @@ -53,6 +55,9 @@ class SettingsFragment : PreferenceFragmentCompat(), SharedPreferences.OnSharedP findPreference("export")?.onPreferenceClickListener = exportClickListener() findPreference("import")?.onPreferenceClickListener = importClickListener() findPreference("status").onPreferenceClickListener = statusClickListener() + val conversationInit = findPreference("emulate_conversations_initialize") + conversationInit?.onPreferenceClickListener = conversationInitClickListener(conversationInit) + findPreference("emulate_conversations")?.onPreferenceChangeListener = emulateConversationChangeListener(conversationInit) } private fun aboutClickListener() = Preference.OnPreferenceClickListener { @@ -73,7 +78,8 @@ class SettingsFragment : PreferenceFragmentCompat(), SharedPreferences.OnSharedP } private fun cleanupClickListener(cleanup: Preference) = Preference.OnPreferenceClickListener { - val ctx = activity?.applicationContext ?: throw IllegalStateException("Context not available") + val ctx = activity?.applicationContext + ?: throw IllegalStateException("Context not available") cleanup.isEnabled = false Toast.makeText(ctx, R.string.cleanup_notification_start, Toast.LENGTH_SHORT).show() @@ -193,6 +199,49 @@ class SettingsFragment : PreferenceFragmentCompat(), SharedPreferences.OnSharedP } } + private fun conversationInitClickListener(conversationInit: Preference) = Preference.OnPreferenceClickListener { + val ctx = activity?.applicationContext + ?: throw IllegalStateException("Context not available") + conversationInit.isEnabled = false + Toast.makeText(ctx, R.string.emulate_conversations_summary, Toast.LENGTH_SHORT).show() + + doAsync { + val messageRepo = Singleton.getMessageRepository(ctx) + val conversationService = Singleton.getConversationService(ctx) + do { + var previous: Plaintext? = null + val messages = messageRepo.findNextLegacyMessages(previous) + messages.forEach { msg -> + if (msg.encoding == Plaintext.Encoding.SIMPLE) { + conversationService.getSubject(listOf(msg))?.let { subject -> + msg.conversationId = UUID.nameUUIDFromBytes(subject.toByteArray()) + messageRepo.save(msg) + Thread.yield() + } + } + } + if (!messages.isEmpty()) { + previous = messages.last() + } + } while (!messages.isEmpty()) + + uiThread { + Toast.makeText( + ctx, + R.string.cleanup_notification_end, + Toast.LENGTH_LONG + ).show() + conversationInit.isEnabled = true + } + } + return@OnPreferenceClickListener true + } + + private fun emulateConversationChangeListener(conversationInit: Preference?) = Preference.OnPreferenceChangeListener { preference, newValue -> + conversationInit?.isEnabled = newValue as Boolean + true + } + companion object { const val WRITE_EXPORT_REQUEST_CODE = 1 const val READ_IMPORT_REQUEST_CODE = 2 diff --git a/app/src/main/java/ch/dissem/apps/abit/repository/AndroidMessageRepository.kt b/app/src/main/java/ch/dissem/apps/abit/repository/AndroidMessageRepository.kt index cec80db..174f9d1 100644 --- a/app/src/main/java/ch/dissem/apps/abit/repository/AndroidMessageRepository.kt +++ b/app/src/main/java/ch/dissem/apps/abit/repository/AndroidMessageRepository.kt @@ -254,6 +254,39 @@ class AndroidMessageRepository(private val sql: SqlHelper) : AbstractMessageRepo sql.writableDatabase.delete(TABLE_NAME, "id = ?", arrayOf(message.id.toString())) } + fun findNextLegacyMessages(previous: Plaintext?, limit: Int = 10): List { + val result = mutableListOf<Plaintext>() + + val projection = arrayOf( + COLUMN_ID, + COLUMN_IV, + COLUMN_TYPE, + COLUMN_SENDER, + COLUMN_RECIPIENT, + COLUMN_DATA, + COLUMN_ACK_DATA, + COLUMN_SENT, + COLUMN_RECEIVED, + COLUMN_STATUS, + COLUMN_TTL, + COLUMN_RETRIES, + COLUMN_NEXT_TRY, + COLUMN_CONVERSATION + ) + + sql.readableDatabase.query( + TABLE_NAME, projection, + "$COLUMN_ID > ${previous?.id ?: Long.MIN_VALUE}", null, null, null, + "$COLUMN_ID ASC", + "$limit" + ).use { c -> + while (c.moveToNext()) { + result.add(getMessage(c)) + } + } + return result + } + companion object { private const val TABLE_NAME = "Message" private const val COLUMN_ID = "id" diff --git a/app/src/main/res/values/strings.xml b/app/src/main/res/values/strings.xml index 8cd8186..630db20 100644 --- a/app/src/main/res/values/strings.xml +++ b/app/src/main/res/values/strings.xml @@ -139,4 +139,5 @@ As an alternative you could configure a trusted node in the settings, but as of <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> + <string name="emulate_conversations_initialize">Group existing messages by subject</string> </resources> diff --git a/app/src/main/res/xml/preferences.xml b/app/src/main/res/xml/preferences.xml index 0a408e5..bf163df 100644 --- a/app/src/main/res/xml/preferences.xml +++ b/app/src/main/res/xml/preferences.xml @@ -10,6 +10,11 @@ android:key="emulate_conversations" android:summary="@string/emulate_conversations_summary" android:title="@string/emulate_conversations" /> + <android.support.v7.preference.Preference + android:defaultValue="true" + android:key="emulate_conversations_initialize" + android:summary="@string/emulate_conversations_summary" + android:title="@string/emulate_conversations_initialize" /> <android.support.v7.preference.SwitchPreferenceCompat android:defaultValue="true" android:key="request_acknowledgements"