🚧 Add code to migrate existing conversations

Work in progress: does work, but usually doesn't finish. This needs to be
moved into some proper batch processing.
This commit is contained in:
Christian Basler 2018-04-13 12:39:59 +02:00
parent 85562efc0d
commit 78f9621afa
4 changed files with 89 additions and 1 deletions

View File

@ -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.Constants.PREFERENCE_TRUSTED_NODE
import ch.dissem.apps.abit.util.Exports import ch.dissem.apps.abit.util.Exports
import ch.dissem.apps.abit.util.Preferences import ch.dissem.apps.abit.util.Preferences
import ch.dissem.bitmessage.entity.Plaintext
import com.mikepenz.aboutlibraries.Libs import com.mikepenz.aboutlibraries.Libs
import com.mikepenz.aboutlibraries.LibsBuilder import com.mikepenz.aboutlibraries.LibsBuilder
import org.jetbrains.anko.doAsync import org.jetbrains.anko.doAsync
import org.jetbrains.anko.support.v4.indeterminateProgressDialog import org.jetbrains.anko.support.v4.indeterminateProgressDialog
import org.jetbrains.anko.support.v4.startActivity import org.jetbrains.anko.support.v4.startActivity
import org.jetbrains.anko.uiThread import org.jetbrains.anko.uiThread
import java.util.*
/** /**
* @author Christian Basler * @author Christian Basler
@ -53,6 +55,9 @@ class SettingsFragment : PreferenceFragmentCompat(), SharedPreferences.OnSharedP
findPreference("export")?.onPreferenceClickListener = exportClickListener() findPreference("export")?.onPreferenceClickListener = exportClickListener()
findPreference("import")?.onPreferenceClickListener = importClickListener() findPreference("import")?.onPreferenceClickListener = importClickListener()
findPreference("status").onPreferenceClickListener = statusClickListener() 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 { private fun aboutClickListener() = Preference.OnPreferenceClickListener {
@ -73,7 +78,8 @@ class SettingsFragment : PreferenceFragmentCompat(), SharedPreferences.OnSharedP
} }
private fun cleanupClickListener(cleanup: Preference) = Preference.OnPreferenceClickListener { 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 cleanup.isEnabled = false
Toast.makeText(ctx, R.string.cleanup_notification_start, Toast.LENGTH_SHORT).show() 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 { companion object {
const val WRITE_EXPORT_REQUEST_CODE = 1 const val WRITE_EXPORT_REQUEST_CODE = 1
const val READ_IMPORT_REQUEST_CODE = 2 const val READ_IMPORT_REQUEST_CODE = 2

View File

@ -254,6 +254,39 @@ class AndroidMessageRepository(private val sql: SqlHelper) : AbstractMessageRepo
sql.writableDatabase.delete(TABLE_NAME, "id = ?", arrayOf(message.id.toString())) sql.writableDatabase.delete(TABLE_NAME, "id = ?", arrayOf(message.id.toString()))
} }
fun findNextLegacyMessages(previous: Plaintext?, limit: Int = 10): List<Plaintext> {
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 { companion object {
private const val TABLE_NAME = "Message" private const val TABLE_NAME = "Message"
private const val COLUMN_ID = "id" private const val COLUMN_ID = "id"

View File

@ -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="context_menu">actions</string>
<string name="emulate_conversations">Guess conversations</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_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> </resources>

View File

@ -10,6 +10,11 @@
android:key="emulate_conversations" android:key="emulate_conversations"
android:summary="@string/emulate_conversations_summary" android:summary="@string/emulate_conversations_summary"
android:title="@string/emulate_conversations" /> 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.support.v7.preference.SwitchPreferenceCompat
android:defaultValue="true" android:defaultValue="true"
android:key="request_acknowledgements" android:key="request_acknowledgements"