Code style improvements (thanks to codebeat.co)

This commit is contained in:
Christian Basler 2017-11-22 21:07:09 +01:00
parent 49d87c3c75
commit dd22caaa50
3 changed files with 174 additions and 141 deletions

View File

@ -20,7 +20,6 @@ import android.app.Activity
import android.content.Context import android.content.Context
import android.content.Intent import android.content.Intent
import android.content.SharedPreferences import android.content.SharedPreferences
import android.net.Uri
import android.os.Bundle import android.os.Bundle
import android.preference.PreferenceManager import android.preference.PreferenceManager
import android.support.v4.content.FileProvider.getUriForFile import android.support.v4.content.FileProvider.getUriForFile
@ -31,24 +30,14 @@ import ch.dissem.apps.abit.service.Singleton
import ch.dissem.apps.abit.synchronization.SyncAdapter import ch.dissem.apps.abit.synchronization.SyncAdapter
import ch.dissem.apps.abit.util.Constants.PREFERENCE_SERVER_POW 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.Preferences import ch.dissem.apps.abit.util.Preferences
import ch.dissem.bitmessage.entity.valueobject.Label
import ch.dissem.bitmessage.exports.ContactExport
import ch.dissem.bitmessage.exports.MessageExport
import ch.dissem.bitmessage.utils.UnixTime
import com.beust.klaxon.JsonArray
import com.beust.klaxon.Parser
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.io.File
import java.io.FileOutputStream
import java.util.zip.ZipEntry
import java.util.zip.ZipInputStream
import java.util.zip.ZipOutputStream
/** /**
* @author Christian Basler * @author Christian Basler
@ -101,43 +90,20 @@ class SettingsFragment : PreferenceFragmentCompat(), SharedPreferences.OnSharedP
findPreference("export")?.onPreferenceClickListener = Preference.OnPreferenceClickListener { findPreference("export")?.onPreferenceClickListener = Preference.OnPreferenceClickListener {
val ctx = context ?: throw IllegalStateException("No context available") val ctx = context ?: throw IllegalStateException("No context available")
val dialog = indeterminateProgressDialog(R.string.export_data_summary, R.string.export_data) indeterminateProgressDialog(R.string.export_data_summary, R.string.export_data).apply {
doAsync { doAsync {
val exportDirectory = Preferences.getExportDirectory(ctx) val exportDirectory = Preferences.getExportDirectory(ctx)
exportDirectory.mkdirs() exportDirectory.mkdirs()
val temp = File(exportDirectory, "export-${UnixTime.now}.zip") val file = Exports.exportData(exportDirectory, ctx)
ZipOutputStream(FileOutputStream(temp)).use { zip -> val contentUri = getUriForFile(ctx, "ch.dissem.apps.abit.fileprovider", file)
zip.putNextEntry(ZipEntry("contacts.json")) val intent = Intent(android.content.Intent.ACTION_SEND)
val addressRepo = Singleton.getAddressRepository(ctx) intent.type = "application/zip"
val exportContacts = ContactExport.exportContacts(addressRepo.getContacts()) intent.putExtra(Intent.EXTRA_SUBJECT, "abit-export.zip")
zip.write( intent.putExtra(Intent.EXTRA_STREAM, contentUri)
exportContacts.toJsonString(true).toByteArray() startActivityForResult(Intent.createChooser(intent, ""), WRITE_EXPORT_REQUEST_CODE)
) uiThread {
zip.closeEntry() dismiss()
}
val messageRepo = Singleton.getMessageRepository(ctx)
zip.putNextEntry(ZipEntry("labels.json"))
val exportLabels = MessageExport.exportLabels(messageRepo.getLabels())
zip.write(
exportLabels.toJsonString(true).toByteArray()
)
zip.closeEntry()
zip.putNextEntry(ZipEntry("messages.json"))
val exportMessages = MessageExport.exportMessages(messageRepo.getAllMessages())
zip.write(
exportMessages.toJsonString(true).toByteArray()
)
zip.closeEntry()
}
val contentUri = getUriForFile(ctx, "ch.dissem.apps.abit.fileprovider", temp)
val intent = Intent(android.content.Intent.ACTION_SEND)
intent.type = "application/zip"
intent.putExtra(Intent.EXTRA_SUBJECT, "abit-export.zip")
intent.putExtra(Intent.EXTRA_STREAM, contentUri)
startActivityForResult(Intent.createChooser(intent, ""), WRITE_EXPORT_REQUEST_CODE)
uiThread {
dialog.dismiss()
} }
} }
return@OnPreferenceClickListener true return@OnPreferenceClickListener true
@ -163,53 +129,19 @@ class SettingsFragment : PreferenceFragmentCompat(), SharedPreferences.OnSharedP
} }
} }
private fun processEntry(ctx: Context, zipFile: Uri, entry: String, processor: (JsonArray<*>) -> Unit) =
ZipInputStream(ctx.contentResolver.openInputStream(zipFile)).use { zip ->
var nextEntry = zip.nextEntry
while (nextEntry != null) {
if (nextEntry.name == entry) {
processor(Parser().parse(zip) as JsonArray<*>)
}
nextEntry = zip.nextEntry
}
}
override fun onActivityResult(requestCode: Int, resultCode: Int, data: Intent?) { override fun onActivityResult(requestCode: Int, resultCode: Int, data: Intent?) {
val ctx = context ?: throw IllegalStateException("No context available") val ctx = context ?: throw IllegalStateException("No context available")
when (requestCode) { when (requestCode) {
WRITE_EXPORT_REQUEST_CODE -> Preferences.cleanupExportDirectory(ctx) WRITE_EXPORT_REQUEST_CODE -> Preferences.cleanupExportDirectory(ctx)
READ_IMPORT_REQUEST_CODE -> { READ_IMPORT_REQUEST_CODE -> {
if (resultCode == Activity.RESULT_OK && data?.data != null) { if (resultCode == Activity.RESULT_OK && data?.data != null) {
val dialog = indeterminateProgressDialog(R.string.import_data_summary, R.string.import_data) indeterminateProgressDialog(R.string.import_data_summary, R.string.import_data).apply {
doAsync { doAsync {
val bmc = Singleton.getBitmessageContext(ctx) Exports.importData(data.data, ctx)
val labels = mutableMapOf<String, Label>() uiThread {
val zipFile = data.data dismiss()
processEntry(ctx, zipFile, "contacts.json") { json ->
ContactExport.importContacts(json).forEach { contact ->
bmc.addresses.save(contact)
} }
} }
bmc.messages.getLabels().forEach { label ->
labels[label.toString()] = label
}
processEntry(ctx, zipFile, "labels.json") { json ->
MessageExport.importLabels(json).forEach { label ->
if (!labels.contains(label.toString())) {
bmc.messages.save(label)
labels[label.toString()] = label
}
}
}
processEntry(ctx, zipFile, "messages.json") { json ->
MessageExport.importMessages(json, labels).forEach { message ->
bmc.messages.save(message)
}
}
uiThread {
dialog.dismiss()
}
} }
} }
} }
@ -227,25 +159,29 @@ class SettingsFragment : PreferenceFragmentCompat(), SharedPreferences.OnSharedP
override fun onSharedPreferenceChanged(sharedPreferences: SharedPreferences, key: String) { override fun onSharedPreferenceChanged(sharedPreferences: SharedPreferences, key: String) {
when (key) { when (key) {
PREFERENCE_TRUSTED_NODE -> { PREFERENCE_TRUSTED_NODE -> toggleSyncTrustedNode(sharedPreferences)
val node = sharedPreferences.getString(PREFERENCE_TRUSTED_NODE, null) PREFERENCE_SERVER_POW -> toggleSyncServerPOW(sharedPreferences)
val ctx = context ?: throw IllegalStateException("No context available") }
if (node != null) { }
SyncAdapter.startSync(ctx)
} else { private fun toggleSyncTrustedNode(sharedPreferences: SharedPreferences) {
SyncAdapter.stopSync(ctx) val node = sharedPreferences.getString(PREFERENCE_TRUSTED_NODE, null)
} val ctx = context ?: throw IllegalStateException("No context available")
} if (node != null) {
PREFERENCE_SERVER_POW -> { SyncAdapter.startSync(ctx)
val node = sharedPreferences.getString(PREFERENCE_TRUSTED_NODE, null) } else {
if (node != null) { SyncAdapter.stopSync(ctx)
val ctx = context ?: throw IllegalStateException("No context available") }
if (sharedPreferences.getBoolean(PREFERENCE_SERVER_POW, false)) { }
SyncAdapter.startPowSync(ctx)
} else { private fun toggleSyncServerPOW(sharedPreferences: SharedPreferences) {
SyncAdapter.stopPowSync(ctx) val node = sharedPreferences.getString(PREFERENCE_TRUSTED_NODE, null)
} if (node != null) {
} val ctx = context ?: throw IllegalStateException("No context available")
if (sharedPreferences.getBoolean(PREFERENCE_SERVER_POW, false)) {
SyncAdapter.startPowSync(ctx)
} else {
SyncAdapter.stopPowSync(ctx)
} }
} }
} }

View File

@ -17,6 +17,7 @@
package ch.dissem.apps.abit.repository package ch.dissem.apps.abit.repository
import android.content.ContentValues import android.content.ContentValues
import android.database.Cursor
import ch.dissem.bitmessage.entity.BitmessageAddress import ch.dissem.bitmessage.entity.BitmessageAddress
import ch.dissem.bitmessage.entity.payload.V3Pubkey import ch.dissem.bitmessage.entity.payload.V3Pubkey
import ch.dissem.bitmessage.entity.payload.V4Pubkey import ch.dissem.bitmessage.entity.payload.V4Pubkey
@ -81,8 +82,8 @@ class AndroidAddressRepository(private val sql: SqlHelper) : AddressRepository {
* @return the ordered list of ids (address strings) * @return the ordered list of ids (address strings)
*/ */
fun getContactIds(): List<String> = findIds( fun getContactIds(): List<String> = findIds(
"private_key IS NULL OR chan = '1'", "private_key IS NULL OR chan = '1'",
"$COLUMN_SUBSCRIBED DESC, $COLUMN_ALIAS IS NULL, $COLUMN_ALIAS, $COLUMN_ADDRESS" "$COLUMN_SUBSCRIBED DESC, $COLUMN_ALIAS IS NULL, $COLUMN_ALIAS, $COLUMN_ADDRESS"
) )
private fun findIds(where: String, orderBy: String): List<String> { private fun findIds(where: String, orderBy: String): List<String> {
@ -94,9 +95,9 @@ class AndroidAddressRepository(private val sql: SqlHelper) : AddressRepository {
val db = sql.readableDatabase val db = sql.readableDatabase
db.query( db.query(
TABLE_NAME, projection, TABLE_NAME, projection,
where, null, null, null, where, null, null, null,
orderBy orderBy
).use { c -> ).use { c ->
while (c.moveToNext()) { while (c.moveToNext()) {
result.add(c.getString(c.getColumnIndex(COLUMN_ADDRESS))) result.add(c.getString(c.getColumnIndex(COLUMN_ADDRESS)))
@ -114,40 +115,42 @@ class AndroidAddressRepository(private val sql: SqlHelper) : AddressRepository {
val db = sql.readableDatabase val db = sql.readableDatabase
db.query( db.query(
TABLE_NAME, projection, TABLE_NAME, projection,
where, null, null, null, null where, null, null, null, null
).use { c -> ).use { c ->
while (c.moveToNext()) { while (c.moveToNext()) {
val address: BitmessageAddress result.add(getAddress(c))
val privateKeyBytes = c.getBlob(c.getColumnIndex(COLUMN_PRIVATE_KEY))
if (privateKeyBytes != null) {
val privateKey = PrivateKey.read(ByteArrayInputStream(privateKeyBytes))
address = BitmessageAddress(privateKey)
} else {
address = BitmessageAddress(c.getString(c.getColumnIndex(COLUMN_ADDRESS)))
val publicKeyBytes = c.getBlob(c.getColumnIndex(COLUMN_PUBLIC_KEY))
if (publicKeyBytes != null) {
var pubkey = Factory.readPubkey(address.version, address
.stream,
ByteArrayInputStream(publicKeyBytes), publicKeyBytes.size,
false)
if (address.version == 4L && pubkey is V3Pubkey) {
pubkey = V4Pubkey(pubkey)
}
address.pubkey = pubkey
}
}
address.alias = c.getString(c.getColumnIndex(COLUMN_ALIAS))
address.isChan = c.getInt(c.getColumnIndex(COLUMN_CHAN)) == 1
address.isSubscribed = c.getInt(c.getColumnIndex(COLUMN_SUBSCRIBED)) == 1
result.add(address)
} }
} }
return result return result
} }
private fun getAddress(c: Cursor): BitmessageAddress {
val address: BitmessageAddress
val privateKeyBytes = c.getBlob(c.getColumnIndex(COLUMN_PRIVATE_KEY))
if (privateKeyBytes != null) {
address = BitmessageAddress(PrivateKey.read(ByteArrayInputStream(privateKeyBytes)))
} else {
address = BitmessageAddress(c.getString(c.getColumnIndex(COLUMN_ADDRESS)))
c.getBlob(c.getColumnIndex(COLUMN_PUBLIC_KEY))?.let { publicKeyBytes ->
val pubkey = Factory.readPubkey(address.version, address.stream,
ByteArrayInputStream(publicKeyBytes), publicKeyBytes.size,
false)
address.pubkey = if (address.version == 4L && pubkey is V3Pubkey) {
V4Pubkey(pubkey)
} else {
pubkey
}
}
}
address.alias = c.getString(c.getColumnIndex(COLUMN_ALIAS))
address.isChan = c.getInt(c.getColumnIndex(COLUMN_CHAN)) == 1
address.isSubscribed = c.getInt(c.getColumnIndex(COLUMN_SUBSCRIBED)) == 1
return address
}
override fun save(address: BitmessageAddress) = if (exists(address)) { override fun save(address: BitmessageAddress) = if (exists(address)) {
update(address) update(address)
} else { } else {
@ -157,8 +160,8 @@ class AndroidAddressRepository(private val sql: SqlHelper) : AddressRepository {
private fun exists(address: BitmessageAddress): Boolean { private fun exists(address: BitmessageAddress): Boolean {
val db = sql.readableDatabase val db = sql.readableDatabase
db.rawQuery( db.rawQuery(
"SELECT COUNT(*) FROM Address WHERE address=?", "SELECT COUNT(*) FROM Address WHERE address=?",
arrayOf(address.address) arrayOf(address.address)
).use { cursor -> ).use { cursor ->
cursor.moveToFirst() cursor.moveToFirst()
return cursor.getInt(0) > 0 return cursor.getInt(0) > 0

View File

@ -0,0 +1,94 @@
package ch.dissem.apps.abit.util
import android.content.Context
import android.net.Uri
import ch.dissem.apps.abit.service.Singleton
import ch.dissem.bitmessage.entity.valueobject.Label
import ch.dissem.bitmessage.exports.ContactExport
import ch.dissem.bitmessage.exports.MessageExport
import ch.dissem.bitmessage.utils.UnixTime
import com.beust.klaxon.JsonArray
import com.beust.klaxon.Parser
import java.io.File
import java.io.FileOutputStream
import java.util.zip.ZipEntry
import java.util.zip.ZipInputStream
import java.util.zip.ZipOutputStream
/**
* Helper object for data export and import.
*/
object Exports {
fun exportData(target: File, ctx: Context): File {
val temp = if (target.isDirectory) {
File(target, "export-${UnixTime.now}.zip")
} else {
target
}
ZipOutputStream(FileOutputStream(temp)).use { zip ->
zip.putNextEntry(ZipEntry("contacts.json"))
val addressRepo = Singleton.getAddressRepository(ctx)
val exportContacts = ContactExport.exportContacts(addressRepo.getContacts())
zip.write(
exportContacts.toJsonString(true).toByteArray()
)
zip.closeEntry()
val messageRepo = Singleton.getMessageRepository(ctx)
zip.putNextEntry(ZipEntry("labels.json"))
val exportLabels = MessageExport.exportLabels(messageRepo.getLabels())
zip.write(
exportLabels.toJsonString(true).toByteArray()
)
zip.closeEntry()
zip.putNextEntry(ZipEntry("messages.json"))
val exportMessages = MessageExport.exportMessages(messageRepo.getAllMessages())
zip.write(
exportMessages.toJsonString(true).toByteArray()
)
zip.closeEntry()
}
return temp
}
fun importData(zipFile: Uri, ctx: Context) {
val bmc = Singleton.getBitmessageContext(ctx)
val labels = mutableMapOf<String, Label>()
processEntry(ctx, zipFile, "contacts.json") { json ->
ContactExport.importContacts(json).forEach { contact ->
bmc.addresses.save(contact)
}
}
bmc.messages.getLabels().forEach { label ->
labels[label.toString()] = label
}
processEntry(ctx, zipFile, "labels.json") { json ->
MessageExport.importLabels(json).forEach { label ->
if (!labels.contains(label.toString())) {
bmc.messages.save(label)
labels[label.toString()] = label
}
}
}
processEntry(ctx, zipFile, "messages.json") { json ->
MessageExport.importMessages(json, labels).forEach { message ->
bmc.messages.save(message)
}
}
}
private fun processEntry(ctx: Context, zipFile: Uri, entry: String, processor: (JsonArray<*>) -> Unit) =
ZipInputStream(ctx.contentResolver.openInputStream(zipFile)).use { zip ->
var nextEntry = zip.nextEntry
while (nextEntry != null) {
if (nextEntry.name == entry) {
processor(Parser().parse(zip) as JsonArray<*>)
}
nextEntry = zip.nextEntry
}
}
}