Bug fixes

- fixed check if connection is allowed (metered/unmetered network)
- label is actually selected when opening the overview
- minor code improvements
- dependency version bumps
This commit is contained in:
Christian Basler 2017-12-30 19:21:25 +01:00
parent f6ebd62c8d
commit d88d3c900e
6 changed files with 127 additions and 130 deletions

View File

@ -51,9 +51,10 @@ android {
//ext.jabitVersion = '2.0.4' //ext.jabitVersion = '2.0.4'
ext.jabitVersion = 'feature-refactoring-SNAPSHOT' ext.jabitVersion = 'feature-refactoring-SNAPSHOT'
ext.supportVersion = '27.0.1' ext.supportVersion = '27.0.2'
dependencies { dependencies {
implementation fileTree(dir: 'libs', include: ['*.jar']) implementation fileTree(dir: 'libs', include: ['*.jar'])
implementation "org.jetbrains.kotlin:kotlin-stdlib:$kotlin_version"
implementation "org.jetbrains.kotlin:kotlin-stdlib-jre7:$kotlin_version" implementation "org.jetbrains.kotlin:kotlin-stdlib-jre7:$kotlin_version"
implementation "org.jetbrains.kotlin:kotlin-reflect:$kotlin_version" implementation "org.jetbrains.kotlin:kotlin-reflect:$kotlin_version"
implementation "org.jetbrains.anko:anko:$anko_version" implementation "org.jetbrains.anko:anko:$anko_version"
@ -74,22 +75,22 @@ dependencies {
implementation 'org.slf4j:slf4j-android:1.7.25' implementation 'org.slf4j:slf4j-android:1.7.25'
implementation 'com.mikepenz:materialize:1.1.0@aar' implementation 'com.mikepenz:materialize:1.1.2@aar'
implementation('com.mikepenz:materialdrawer:5.9.5@aar') { implementation('com.mikepenz:materialdrawer:6.0.2@aar') {
transitive = true transitive = true
} }
implementation('com.mikepenz:aboutlibraries:5.9.7@aar') { implementation('com.mikepenz:aboutlibraries:6.0.1@aar') {
transitive = true transitive = true
} }
implementation "com.mikepenz:iconics-core:2.9.3@aar" implementation "com.mikepenz:iconics-core:3.0.0@aar"
implementation "com.mikepenz:iconics-views:2.9.3@aar" implementation "com.mikepenz:iconics-views:3.0.0@aar"
implementation 'com.mikepenz:google-material-typeface:3.0.1.1.original@aar' implementation 'com.mikepenz:google-material-typeface:3.0.1.2.original@aar'
implementation 'com.mikepenz:community-material-typeface:1.9.32.2@aar' implementation 'com.mikepenz:community-material-typeface:2.0.46.1@aar'
implementation 'com.journeyapps:zxing-android-embedded:3.5.0@aar' implementation 'com.journeyapps:zxing-android-embedded:3.5.0@aar'
implementation 'com.google.zxing:core:3.3.1' implementation 'com.google.zxing:core:3.3.1'
implementation 'com.github.kobakei:MaterialFabSpeedDial:1.1.7' implementation 'com.github.kobakei:MaterialFabSpeedDial:1.1.8'
implementation 'com.github.amlcurran.showcaseview:library:5.4.3' implementation 'com.github.amlcurran.showcaseview:library:5.4.3'
implementation('com.github.h6ah4i:android-advancedrecyclerview:0.11.0@aar') { implementation('com.github.h6ah4i:android-advancedrecyclerview:0.11.0@aar') {
transitive = true transitive = true
@ -98,12 +99,12 @@ dependencies {
implementation 'com.android.support.constraint:constraint-layout:1.0.2' implementation 'com.android.support.constraint:constraint-layout:1.0.2'
testImplementation 'junit:junit:4.12' testImplementation 'junit:junit:4.12'
testImplementation 'org.mockito:mockito-core:2.11.0' testImplementation 'org.mockito:mockito-core:2.13.0'
testImplementation 'org.hamcrest:hamcrest-library:1.3' testImplementation 'org.hamcrest:hamcrest-library:1.3'
testImplementation 'com.nhaarman:mockito-kotlin-kt1.1:1.5.0' testImplementation 'com.nhaarman:mockito-kotlin-kt1.1:1.5.0'
testImplementation "org.jetbrains.kotlin:kotlin-reflect:$kotlin_version" testImplementation "org.jetbrains.kotlin:kotlin-reflect:$kotlin_version"
testImplementation 'org.robolectric:robolectric:3.5' testImplementation 'org.robolectric:robolectric:3.6.1'
testImplementation "org.robolectric:shadows-multidex:3.5" testImplementation "org.robolectric:shadows-multidex:3.6.1"
androidTestImplementation "com.android.support:multidex:1.0.2" androidTestImplementation "com.android.support:multidex:1.0.2"
} }

View File

@ -4,9 +4,9 @@
xmlns:android="http://schemas.android.com/apk/res/android" xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"> xmlns:tools="http://schemas.android.com/tools">
<uses-permission android:name="android.permission.ACCESS_WIFI_STATE"/>
<uses-permission android:name="android.permission.INTERNET"/> <uses-permission android:name="android.permission.INTERNET"/>
<uses-permission android:name="android.permission.ACCESS_NETWORK_STATE"/> <uses-permission android:name="android.permission.ACCESS_NETWORK_STATE"/>
<uses-permission android:name="android.permission.ACCESS_WIFI_STATE"/>
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE"/> <uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE"/>
<uses-permission android:name="android.permission.AUTHENTICATE_ACCOUNTS"/> <uses-permission android:name="android.permission.AUTHENTICATE_ACCOUNTS"/>
<uses-permission android:name="android.permission.READ_SYNC_SETTINGS"/> <uses-permission android:name="android.permission.READ_SYNC_SETTINGS"/>

View File

@ -114,9 +114,9 @@ class MainActivity : AppCompatActivity(), ListSelectionListener<Serializable> {
val listFragment = MessageListFragment() val listFragment = MessageListFragment()
supportFragmentManager supportFragmentManager
.beginTransaction() .beginTransaction()
.replace(R.id.item_list, listFragment) .replace(R.id.item_list, listFragment)
.commit() .commit()
if (findViewById<View>(R.id.message_detail_container) != null) { if (findViewById<View>(R.id.message_detail_container) != null) {
// The detail container view will be present only in the // The detail container view will be present only in the
@ -149,40 +149,38 @@ class MainActivity : AppCompatActivity(), ListSelectionListener<Serializable> {
} }
if (drawer.isDrawerOpen) { if (drawer.isDrawerOpen) {
val lps = RelativeLayout.LayoutParams(ViewGroup val lps = RelativeLayout.LayoutParams(ViewGroup
.LayoutParams.WRAP_CONTENT, ViewGroup.LayoutParams.WRAP_CONTENT) .LayoutParams.WRAP_CONTENT, ViewGroup.LayoutParams.WRAP_CONTENT)
lps.addRule(RelativeLayout.ALIGN_PARENT_BOTTOM) lps.addRule(RelativeLayout.ALIGN_PARENT_BOTTOM)
lps.addRule(RelativeLayout.ALIGN_PARENT_LEFT) lps.addRule(RelativeLayout.ALIGN_PARENT_LEFT)
val margin = ((resources.displayMetrics.density * 12) as Number).toInt() val margin = ((resources.displayMetrics.density * 12) as Number).toInt()
lps.setMargins(margin, margin, margin, margin) lps.setMargins(margin, margin, margin, margin)
ShowcaseView.Builder(this) ShowcaseView.Builder(this)
.withMaterialShowcase() .withMaterialShowcase()
.setStyle(R.style.CustomShowcaseTheme) .setStyle(R.style.CustomShowcaseTheme)
.setContentTitle(R.string.full_node) .setContentTitle(R.string.full_node)
.setContentText(R.string.full_node_description) .setContentText(R.string.full_node_description)
.setTarget { .setTarget {
val view = drawer.stickyFooter val view = drawer.stickyFooter
val location = IntArray(2) val location = IntArray(2)
view.getLocationInWindow(location) view.getLocationInWindow(location)
val x = location[0] + 7 * view.width / 8 val x = location[0] + 7 * view.width / 8
val y = location[1] + view.height / 2 val y = location[1] + view.height / 2
Point(x, y) Point(x, y)
} }
.replaceEndButton(R.layout.showcase_button) .replaceEndButton(R.layout.showcase_button)
.hideOnTouchOutside() .hideOnTouchOutside()
.build() .build()
.setButtonPosition(lps) .setButtonPosition(lps)
} }
} }
private fun <F> changeList(listFragment: F) where F : Fragment, F : ListHolder<*> { private fun <F> changeList(listFragment: F) where F : Fragment, F : ListHolder<*> {
if (active) { if (active) {
val transaction = supportFragmentManager val transaction = supportFragmentManager.beginTransaction()
.beginTransaction()
transaction.replace(R.id.item_list, listFragment) transaction.replace(R.id.item_list, listFragment)
val detailFragment = supportFragmentManager.findFragmentById(R.id.message_detail_container) supportFragmentManager.findFragmentById(R.id.message_detail_container)?.let {
if (detailFragment != null) { transaction.remove(it)
transaction.remove(detailFragment)
} }
transaction.addToBackStack(null).commit() transaction.addToBackStack(null).commit()
@ -197,67 +195,67 @@ class MainActivity : AppCompatActivity(), ListSelectionListener<Serializable> {
private fun createDrawer(toolbar: Toolbar) { private fun createDrawer(toolbar: Toolbar) {
val profiles = ArrayList<IProfile<*>>() val profiles = ArrayList<IProfile<*>>()
profiles.add(ProfileSettingDrawerItem() profiles.add(ProfileSettingDrawerItem()
.withName(getString(R.string.add_identity)) .withName(getString(R.string.add_identity))
.withDescription(getString(R.string.add_identity_summary)) .withDescription(getString(R.string.add_identity_summary))
.withIcon(IconicsDrawable(this, GoogleMaterial.Icon.gmd_add) .withIcon(IconicsDrawable(this, GoogleMaterial.Icon.gmd_add)
.actionBar() .actionBar()
.paddingDp(5) .paddingDp(5)
.colorRes(R.color.icons)) .colorRes(R.color.icons))
.withIdentifier(ADD_IDENTITY.toLong()) .withIdentifier(ADD_IDENTITY.toLong())
) )
profiles.add(ProfileSettingDrawerItem() profiles.add(ProfileSettingDrawerItem()
.withName(getString(R.string.manage_identity)) .withName(getString(R.string.manage_identity))
.withIcon(GoogleMaterial.Icon.gmd_settings) .withIcon(GoogleMaterial.Icon.gmd_settings)
.withIdentifier(MANAGE_IDENTITY.toLong()) .withIdentifier(MANAGE_IDENTITY.toLong())
) )
// Create the AccountHeader // Create the AccountHeader
accountHeader = AccountHeaderBuilder() accountHeader = AccountHeaderBuilder()
.withActivity(this) .withActivity(this)
.withHeaderBackground(R.drawable.header) .withHeaderBackground(R.drawable.header)
.withProfiles(profiles) .withProfiles(profiles)
.withOnAccountHeaderProfileImageListener(ProfileImageListener(this)) .withOnAccountHeaderProfileImageListener(ProfileImageListener(this))
.withOnAccountHeaderListener(ProfileSelectionListener(this@MainActivity, supportFragmentManager)) .withOnAccountHeaderListener(ProfileSelectionListener(this@MainActivity, supportFragmentManager))
.build() .build()
if (profiles.size > 2) { // There's always the add and manage identity items if (profiles.size > 2) { // There's always the add and manage identity items
accountHeader.setActiveProfile(profiles[0], true) accountHeader.setActiveProfile(profiles[0], true)
} }
val drawerItems = ArrayList<IDrawerItem<*, *>>() val drawerItems = ArrayList<IDrawerItem<*, *>>()
drawerItems.add(PrimaryDrawerItem() drawerItems.add(PrimaryDrawerItem()
.withName(R.string.archive) .withName(R.string.archive)
.withTag(LABEL_ARCHIVE) .withTag(LABEL_ARCHIVE)
.withIcon(CommunityMaterial.Icon.cmd_archive) .withIcon(CommunityMaterial.Icon.cmd_archive)
) )
drawerItems.add(DividerDrawerItem()) drawerItems.add(DividerDrawerItem())
drawerItems.add(PrimaryDrawerItem() drawerItems.add(PrimaryDrawerItem()
.withName(R.string.contacts_and_subscriptions) .withName(R.string.contacts_and_subscriptions)
.withIcon(GoogleMaterial.Icon.gmd_contacts)) .withIcon(GoogleMaterial.Icon.gmd_contacts))
drawerItems.add(PrimaryDrawerItem() drawerItems.add(PrimaryDrawerItem()
.withName(R.string.settings) .withName(R.string.settings)
.withIcon(GoogleMaterial.Icon.gmd_settings)) .withIcon(GoogleMaterial.Icon.gmd_settings))
nodeSwitch = SwitchDrawerItem() nodeSwitch = SwitchDrawerItem()
.withIdentifier(ID_NODE_SWITCH) .withIdentifier(ID_NODE_SWITCH)
.withName(R.string.full_node) .withName(R.string.full_node)
.withIcon(CommunityMaterial.Icon.cmd_cloud_outline) .withIcon(CommunityMaterial.Icon.cmd_cloud_outline)
.withChecked(Preferences.isFullNodeActive(this)) .withChecked(Preferences.isFullNodeActive(this))
.withOnCheckedChangeListener { _, _, isChecked -> .withOnCheckedChangeListener { _, _, isChecked ->
if (isChecked) { if (isChecked) {
NetworkUtils.enableNode(this@MainActivity) NetworkUtils.enableNode(this@MainActivity)
} else { } else {
NetworkUtils.disableNode(this@MainActivity) NetworkUtils.disableNode(this@MainActivity)
}
} }
}
drawer = DrawerBuilder() drawer = DrawerBuilder()
.withActivity(this) .withActivity(this)
.withToolbar(toolbar) .withToolbar(toolbar)
.withAccountHeader(accountHeader) .withAccountHeader(accountHeader)
.withDrawerItems(drawerItems) .withDrawerItems(drawerItems)
.addStickyDrawerItems(nodeSwitch) .addStickyDrawerItems(nodeSwitch)
.withOnDrawerItemClickListener(DrawerItemClickListener()) .withOnDrawerItemClickListener(DrawerItemClickListener())
.withShowDrawerOnFirstLaunch(true) .withShowDrawerOnFirstLaunch(true)
.build() .build()
loadDrawerItemsAsynchronously() loadDrawerItemsAsynchronously()
} }
@ -289,10 +287,8 @@ class MainActivity : AppCompatActivity(), ListSelectionListener<Serializable> {
for (label in labels) { for (label in labels) {
addLabelEntry(label) addLabelEntry(label)
} }
val selectedDrawerItem = drawer.getDrawerItem(selectedLabel) drawer.setSelection(selectedLabel?.id as Long)
if (selectedDrawerItem != null) { updateUnread()
drawer.setSelection(selectedDrawerItem)
}
} }
} }
} }
@ -338,10 +334,10 @@ class MainActivity : AppCompatActivity(), ListSelectionListener<Serializable> {
} }
R.string.settings -> { R.string.settings -> {
supportFragmentManager supportFragmentManager
.beginTransaction() .beginTransaction()
.replace(R.id.item_list, SettingsFragment()) .replace(R.id.item_list, SettingsFragment())
.addToBackStack(null) .addToBackStack(null)
.commit() .commit()
return false return false
} }
R.string.full_node -> return true R.string.full_node -> return true
@ -385,16 +381,16 @@ class MainActivity : AppCompatActivity(), ListSelectionListener<Serializable> {
fun addIdentityEntry(identity: BitmessageAddress) { fun addIdentityEntry(identity: BitmessageAddress) {
val newProfile = ProfileDrawerItem() val newProfile = ProfileDrawerItem()
.withIcon(Identicon(identity)) .withIcon(Identicon(identity))
.withName(identity.toString()) .withName(identity.toString())
.withNameShown(true) .withNameShown(true)
.withEmail(identity.address) .withEmail(identity.address)
.withTag(identity) .withTag(identity)
if (accountHeader.profiles != null) { if (accountHeader.profiles != null) {
// we know that there are 2 setting elements. // we know that there are 2 setting elements.
// Set the new profile above them ;) // Set the new profile above them ;)
accountHeader.addProfile( accountHeader.addProfile(
newProfile, accountHeader.profiles.size - 2) newProfile, accountHeader.profiles.size - 2)
} else { } else {
accountHeader.addProfiles(newProfile) accountHeader.addProfiles(newProfile)
} }
@ -402,10 +398,11 @@ class MainActivity : AppCompatActivity(), ListSelectionListener<Serializable> {
private fun addLabelEntry(label: Label) { private fun addLabelEntry(label: Label) {
val item = PrimaryDrawerItem() val item = PrimaryDrawerItem()
.withName(label.toString()) .withIdentifier(label.id as Long)
.withTag(label) .withName(label.toString())
.withIcon(Labels.getIcon(label)) .withTag(label)
.withIconColor(Labels.getColor(label)) .withIcon(Labels.getIcon(label))
.withIconColor(Labels.getColor(label))
drawer.addItemAtPosition(item, drawer.drawerItems.size - 3) drawer.addItemAtPosition(item, drawer.drawerItems.size - 3)
} }
@ -414,8 +411,8 @@ class MainActivity : AppCompatActivity(), ListSelectionListener<Serializable> {
if (profile is ProfileDrawerItem) { if (profile is ProfileDrawerItem) {
if (identity == profile.tag) { if (identity == profile.tag) {
profile profile
.withName(identity.toString()) .withName(identity.toString())
.withTag(identity) .withTag(identity)
return return
} }
} }
@ -468,8 +465,8 @@ class MainActivity : AppCompatActivity(), ListSelectionListener<Serializable> {
} }
fragment.arguments = arguments fragment.arguments = arguments
supportFragmentManager.beginTransaction() supportFragmentManager.beginTransaction()
.replace(R.id.message_detail_container, fragment) .replace(R.id.message_detail_container, fragment)
.commit() .commit()
} else { } else {
// In single-pane mode, simply start the detail activity // In single-pane mode, simply start the detail activity
// for the selected item ID. // for the selected item ID.
@ -490,8 +487,8 @@ class MainActivity : AppCompatActivity(), ListSelectionListener<Serializable> {
fun setDetailView(fragment: Fragment) { fun setDetailView(fragment: Fragment) {
if (hasDetailPane) { if (hasDetailPane) {
supportFragmentManager.beginTransaction() supportFragmentManager.beginTransaction()
.replace(R.id.message_detail_container, fragment) .replace(R.id.message_detail_container, fragment)
.commit() .commit()
} }
} }
@ -513,10 +510,9 @@ class MainActivity : AppCompatActivity(), ListSelectionListener<Serializable> {
private var instance: WeakReference<MainActivity>? = null private var instance: WeakReference<MainActivity>? = null
fun updateNodeSwitch() { fun updateNodeSwitch() {
val i = getInstance() getInstance()?.apply {
i?.apply {
runOnUiThread { runOnUiThread {
nodeSwitch.withChecked(Preferences.isFullNodeActive(i)) nodeSwitch.withChecked(Preferences.isFullNodeActive(this))
drawer.updateStickyFooterItem(nodeSwitch) drawer.updateStickyFooterItem(nodeSwitch)
} }
} }

View File

@ -120,31 +120,31 @@ class AndroidAddressRepository(private val sql: SqlHelper) : AddressRepository {
private fun getAddress(c: Cursor): BitmessageAddress { private fun getAddress(c: Cursor): BitmessageAddress {
val privateKeyBytes = c.getBlob(c.getColumnIndex(COLUMN_PRIVATE_KEY)) fun getIdentity(c: Cursor) = c.getBlob(c.getColumnIndex(COLUMN_PRIVATE_KEY))?.let {
val address = privateKeyBytes?.let { BitmessageAddress(PrivateKey.read(ByteArrayInputStream(it)))
BitmessageAddress(PrivateKey.read(ByteArrayInputStream(privateKeyBytes))) }
} ?:
BitmessageAddress(c.getString(c.getColumnIndex(COLUMN_ADDRESS))).also { address -> fun getContact(c: Cursor) = BitmessageAddress(c.getString(c.getColumnIndex(COLUMN_ADDRESS))).also { address ->
c.getBlob(c.getColumnIndex(COLUMN_PUBLIC_KEY))?.let { publicKeyBytes -> c.getBlob(c.getColumnIndex(COLUMN_PUBLIC_KEY))?.let { publicKeyBytes ->
Factory.readPubkey( Factory.readPubkey(
version = address.version, stream = address.stream, version = address.version, stream = address.stream,
input = ByteArrayInputStream(publicKeyBytes), length = publicKeyBytes.size, input = ByteArrayInputStream(publicKeyBytes), length = publicKeyBytes.size,
encrypted = false encrypted = false
).let { ).let {
address.pubkey = if (address.version == 4L && it is V3Pubkey) { address.pubkey = if (address.version == 4L && it is V3Pubkey) {
V4Pubkey(it) V4Pubkey(it)
} else { } else {
it it
}
} }
} }
} }
}
address.alias = c.getString(c.getColumnIndex(COLUMN_ALIAS)) return (getIdentity(c) ?: getContact(c)).apply {
address.isChan = c.getInt(c.getColumnIndex(COLUMN_CHAN)) == 1 alias = c.getString(c.getColumnIndex(COLUMN_ALIAS))
address.isSubscribed = c.getInt(c.getColumnIndex(COLUMN_SUBSCRIBED)) == 1 isChan = c.getInt(c.getColumnIndex(COLUMN_CHAN)) == 1
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)) {

View File

@ -88,7 +88,7 @@ object Preferences {
return preferences.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 { fun isWifiOnly(ctx: Context): Boolean {
val preferences = PreferenceManager.getDefaultSharedPreferences(ctx) val preferences = PreferenceManager.getDefaultSharedPreferences(ctx)

View File

@ -1,6 +1,6 @@
buildscript { buildscript {
ext.kotlin_version = '1.1.61' ext.kotlin_version = '1.2.10'
ext.anko_version = '0.10.2' ext.anko_version = '0.10.4'
repositories { repositories {
jcenter() jcenter()
google() google()