🤯 Update dependencies, switch to AndroidX

This commit is contained in:
Christian Basler 2018-09-27 07:19:03 +02:00
parent e67a4ea71b
commit 0405d9e04f
88 changed files with 940 additions and 1192 deletions

View File

@ -13,8 +13,8 @@ if (project.hasProperty("project.configs")
//noinspection GroovyMissingReturnStatement //noinspection GroovyMissingReturnStatement
android { android {
compileSdkVersion 27 compileSdkVersion 28
buildToolsVersion "27.0.3" buildToolsVersion "28.0.3"
signingConfigs { signingConfigs {
release release
@ -22,7 +22,7 @@ android {
defaultConfig { defaultConfig {
applicationId "ch.dissem.apps.${appName.toLowerCase()}" applicationId "ch.dissem.apps.${appName.toLowerCase()}"
minSdkVersion 21 minSdkVersion 21
targetSdkVersion 27 targetSdkVersion 28
versionCode 23 versionCode 23
versionName "1.0-rc1" versionName "1.0-rc1"
multiDexEnabled true multiDexEnabled true
@ -62,13 +62,16 @@ dependencies {
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"
implementation "com.android.support:appcompat-v7:$supportVersion" implementation 'androidx.appcompat:appcompat:1.0.0'
implementation "com.android.support:preference-v7:$supportVersion" implementation 'androidx.preference:preference:1.0.0'
implementation "com.android.support:cardview-v7:$supportVersion" implementation 'androidx.cardview:cardview:1.0.0'
implementation "com.android.support:support-v13:$supportVersion" implementation 'androidx.legacy:legacy-support-v13:1.0.0'
implementation "com.android.support:preference-v14:$supportVersion" implementation 'androidx.legacy:legacy-preference-v14:1.0.0'
implementation "com.android.support:design:$supportVersion" implementation 'com.google.android.material:material:1.0.0'
implementation "com.android.support:multidex:1.0.3" implementation 'androidx.multidex:multidex:2.0.0'
implementation 'androidx.core:core-ktx:1.0.0'
implementation 'androidx.sqlite:sqlite-ktx:2.0.0-rc01'
implementation 'androidx.fragment:fragment-ktx:1.0.0'
implementation "ch.dissem.jabit:jabit-core:$jabitVersion" implementation "ch.dissem.jabit:jabit-core:$jabitVersion"
implementation "ch.dissem.jabit:jabit-networking:$jabitVersion" implementation "ch.dissem.jabit:jabit-networking:$jabitVersion"
@ -80,15 +83,15 @@ dependencies {
implementation 'org.slf4j:slf4j-android:1.7.25' implementation 'org.slf4j:slf4j-android:1.7.25'
implementation 'com.mikepenz:materialize:1.1.2@aar' implementation 'com.mikepenz:materialize:1.2.0-rc01@aar'
implementation('com.mikepenz:materialdrawer:6.0.8@aar') { implementation('com.mikepenz:materialdrawer:6.1.0-rc01.2@aar') {
transitive = true transitive = true
} }
implementation('com.mikepenz:aboutlibraries:6.0.9@aar') { implementation('com.mikepenz:aboutlibraries:6.2.0-rc01@aar') {
transitive = true transitive = true
} }
implementation "com.mikepenz:iconics-core:3.0.4@aar" implementation "com.mikepenz:iconics-core:3.1.0-rc01@aar"
implementation "com.mikepenz:iconics-views:3.0.4@aar" implementation "com.mikepenz:iconics-views:3.1.0-rc01@aar"
implementation 'com.mikepenz:google-material-typeface:3.0.1.2.original@aar' implementation 'com.mikepenz:google-material-typeface:3.0.1.2.original@aar'
implementation 'com.mikepenz:community-material-typeface:2.0.46.1@aar' implementation 'com.mikepenz:community-material-typeface:2.0.46.1@aar'
@ -97,11 +100,12 @@ dependencies {
implementation 'com.github.kobakei:MaterialFabSpeedDial:1.2.0' implementation 'com.github.kobakei:MaterialFabSpeedDial:1.2.0'
implementation 'com.github.deano2390:MaterialShowcaseView:1.2.0@aar' implementation 'com.github.deano2390:MaterialShowcaseView:1.2.0@aar'
implementation('com.github.h6ah4i:android-advancedrecyclerview:0.11.0@aar') {
transitive = true
}
implementation 'com.github.angads25:filepicker:1.1.1' implementation 'com.github.angads25:filepicker:1.1.1'
implementation 'com.android.support.constraint:constraint-layout:1.1.2' implementation 'androidx.constraintlayout:constraintlayout:2.0.0-alpha2'
implementation "io.reactivex.rxjava2:rxjava:2.2.2"
implementation "io.reactivex.rxjava2:rxkotlin:2.3.0"
implementation "io.reactivex.rxjava2:rxandroid:2.1.0"
testImplementation 'junit:junit:4.12' testImplementation 'junit:junit:4.12'
testImplementation 'org.mockito:mockito-core:2.19.0' testImplementation 'org.mockito:mockito-core:2.19.0'
@ -111,7 +115,7 @@ dependencies {
testImplementation 'org.robolectric:robolectric:3.7.1' testImplementation 'org.robolectric:robolectric:3.7.1'
testImplementation "org.robolectric:shadows-multidex:3.7.1" testImplementation "org.robolectric:shadows-multidex:3.7.1"
androidTestImplementation "com.android.support:multidex:1.0.3" androidTestImplementation "androidx.multidex:multidex:2.0.0"
} }
idea.module { idea.module {

View File

@ -11,9 +11,10 @@
<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" />
<uses-permission android:name="android.permission.WRITE_SYNC_SETTINGS" /> <uses-permission android:name="android.permission.WRITE_SYNC_SETTINGS" />
<uses-permission android:name="android.permission.FOREGROUND_SERVICE" />
<application <application
android:name="android.support.multidex.MultiDexApplication" android:name="androidx.multidex.MultiDexApplication"
android:allowBackup="false" android:allowBackup="false"
android:icon="@mipmap/ic_launcher" android:icon="@mipmap/ic_launcher"
android:label="@string/app_name" android:label="@string/app_name"
@ -124,7 +125,7 @@
<!-- Exports --> <!-- Exports -->
<provider <provider
android:name="android.support.v4.content.FileProvider" android:name="androidx.core.content.FileProvider"
android:authorities="ch.dissem.apps.abit.fileprovider" android:authorities="ch.dissem.apps.abit.fileprovider"
android:exported="false" android:exported="false"
android:grantUriPermissions="true"> android:grantUriPermissions="true">

View File

@ -18,7 +18,7 @@ package ch.dissem.apps.abit
import android.content.Context import android.content.Context
import android.os.Bundle import android.os.Bundle
import android.support.v4.app.ListFragment import androidx.fragment.app.ListFragment
import android.view.View import android.view.View
import android.widget.ListView import android.widget.ListView

View File

@ -19,7 +19,7 @@ package ch.dissem.apps.abit
import android.app.AlertDialog import android.app.AlertDialog
import android.content.Intent import android.content.Intent
import android.os.Bundle import android.os.Bundle
import android.support.v4.app.Fragment import androidx.fragment.app.Fragment
import android.text.Editable import android.text.Editable
import android.text.TextWatcher import android.text.TextWatcher
import android.view.* import android.view.*

View File

@ -28,7 +28,6 @@ import android.widget.ImageView
import android.widget.TextView import android.widget.TextView
import ch.dissem.apps.abit.service.Singleton import ch.dissem.apps.abit.service.Singleton
import ch.dissem.bitmessage.entity.BitmessageAddress import ch.dissem.bitmessage.entity.BitmessageAddress
import com.google.zxing.integration.android.IntentIntegrator
import io.github.kobakei.materialfabspeeddial.FabSpeedDialMenu import io.github.kobakei.materialfabspeeddial.FabSpeedDialMenu
import org.jetbrains.anko.doAsync import org.jetbrains.anko.doAsync
import org.jetbrains.anko.uiThread import org.jetbrains.anko.uiThread
@ -44,7 +43,7 @@ class AddressListFragment : AbstractItemListFragment<Void, BitmessageAddress>()
super.onCreate(savedInstanceState) super.onCreate(savedInstanceState)
adapter = object : ArrayAdapter<BitmessageAddress>( adapter = object : ArrayAdapter<BitmessageAddress>(
activity, activity!!,
R.layout.subscription_row, R.layout.subscription_row,
R.id.name, R.id.name,
LinkedList() LinkedList()
@ -109,9 +108,10 @@ class AddressListFragment : AbstractItemListFragment<Void, BitmessageAddress>()
activity.initFab(R.drawable.ic_action_add_contact, menu) activity.initFab(R.drawable.ic_action_add_contact, menu)
.addOnMenuItemClickListener { _, _, itemId -> .addOnMenuItemClickListener { _, _, itemId ->
when (itemId) { when (itemId) {
1 -> IntentIntegrator.forSupportFragment(this@AddressListFragment) // FIXME
.setDesiredBarcodeFormats(IntentIntegrator.QR_CODE) // 1 -> IntentIntegrator.forSupportFragment(this@AddressListFragment)
.initiateScan() // .setDesiredBarcodeFormats(IntentIntegrator.QR_CODE)
// .initiateScan()
2 -> { 2 -> {
val intent = Intent(getActivity(), CreateAddressActivity::class.java) val intent = Intent(getActivity(), CreateAddressActivity::class.java)
startActivity(intent) startActivity(intent)

View File

@ -20,8 +20,8 @@ import android.app.Activity
import android.content.Context import android.content.Context
import android.content.Intent import android.content.Intent
import android.os.Bundle import android.os.Bundle
import android.support.v4.app.Fragment import androidx.fragment.app.Fragment
import android.support.v7.app.AppCompatActivity import androidx.appcompat.app.AppCompatActivity
import ch.dissem.apps.abit.service.Singleton import ch.dissem.apps.abit.service.Singleton
import ch.dissem.bitmessage.entity.Plaintext import ch.dissem.bitmessage.entity.Plaintext
import ch.dissem.bitmessage.entity.Plaintext.Encoding.EXTENDED import ch.dissem.bitmessage.entity.Plaintext.Encoding.EXTENDED

View File

@ -20,7 +20,7 @@ import android.app.Activity.RESULT_OK
import android.content.Context import android.content.Context
import android.content.Intent import android.content.Intent
import android.os.Bundle import android.os.Bundle
import android.support.v4.app.Fragment import androidx.fragment.app.Fragment
import android.view.* import android.view.*
import android.widget.AdapterView import android.widget.AdapterView
import android.widget.Toast import android.widget.Toast
@ -89,10 +89,10 @@ class ComposeMessageFragment : Fragment() {
recipient = getSerializable(EXTRA_RECIPIENT) as BitmessageAddress recipient = getSerializable(EXTRA_RECIPIENT) as BitmessageAddress
} }
if (containsKey(EXTRA_SUBJECT)) { if (containsKey(EXTRA_SUBJECT)) {
subject = getString(EXTRA_SUBJECT) subject = getString(EXTRA_SUBJECT) ?: throw IllegalStateException("EXTRA_SUBJECT expected")
} }
if (containsKey(EXTRA_CONTENT)) { if (containsKey(EXTRA_CONTENT)) {
content = getString(EXTRA_CONTENT) content = getString(EXTRA_CONTENT) ?: throw IllegalStateException("EXTRA_CONTENT expected")
} }
encoding = getSerializable(EXTRA_ENCODING) as? Plaintext.Encoding ?: Plaintext.Encoding.SIMPLE encoding = getSerializable(EXTRA_ENCODING) as? Plaintext.Encoding ?: Plaintext.Encoding.SIMPLE

View File

@ -17,8 +17,8 @@
package ch.dissem.apps.abit package ch.dissem.apps.abit
import android.os.Bundle import android.os.Bundle
import android.support.v4.app.Fragment import androidx.fragment.app.Fragment
import android.support.v7.widget.LinearLayoutManager import androidx.recyclerview.widget.LinearLayoutManager
import android.view.* import android.view.*
import ch.dissem.apps.abit.adapter.ConversationAdapter import ch.dissem.apps.abit.adapter.ConversationAdapter
import ch.dissem.apps.abit.service.Singleton import ch.dissem.apps.abit.service.Singleton
@ -74,8 +74,7 @@ class ConversationDetailFragment : Fragment() {
item?.let { item -> item?.let { item ->
subject.text = item.subject subject.text = item.subject
avatar.setImageDrawable(MultiIdenticon(item.participants)) avatar.setImageDrawable(MultiIdenticon(item.participants))
messages.adapter = messages.adapter = ConversationAdapter(ctx, this@ConversationDetailFragment, item, Singleton.currentLabel)
ConversationAdapter(ctx, this@ConversationDetailFragment, item, Singleton.currentLabel.value)
messages.layoutManager = LinearLayoutManager(activity) messages.layoutManager = LinearLayoutManager(activity)
} }
} }

View File

@ -19,36 +19,29 @@ package ch.dissem.apps.abit
import android.content.Intent import android.content.Intent
import android.os.Bundle import android.os.Bundle
import android.support.v4.app.Fragment
import android.support.v4.content.ContextCompat
import android.support.v7.widget.LinearLayoutManager
import android.support.v7.widget.RecyclerView
import android.support.v7.widget.RecyclerView.OnScrollListener
import android.view.* import android.view.*
import android.widget.Toast import android.widget.Toast
import androidx.fragment.app.Fragment
import androidx.recyclerview.widget.ItemTouchHelper
import androidx.recyclerview.widget.LinearLayoutManager
import androidx.recyclerview.widget.RecyclerView
import androidx.recyclerview.widget.RecyclerView.OnScrollListener
import ch.dissem.apps.abit.ComposeMessageActivity.Companion.EXTRA_BROADCAST import ch.dissem.apps.abit.ComposeMessageActivity.Companion.EXTRA_BROADCAST
import ch.dissem.apps.abit.ComposeMessageActivity.Companion.EXTRA_IDENTITY import ch.dissem.apps.abit.ComposeMessageActivity.Companion.EXTRA_IDENTITY
import ch.dissem.apps.abit.adapter.EventListener
import ch.dissem.apps.abit.adapter.SwipeToDeleteCallback
import ch.dissem.apps.abit.adapter.SwipeableConversationAdapter import ch.dissem.apps.abit.adapter.SwipeableConversationAdapter
import ch.dissem.apps.abit.listener.ListSelectionListener import ch.dissem.apps.abit.listener.ListSelectionListener
import ch.dissem.apps.abit.repository.AndroidMessageRepository import ch.dissem.apps.abit.repository.AndroidMessageRepository
import ch.dissem.apps.abit.service.Singleton import ch.dissem.apps.abit.service.Singleton
import ch.dissem.apps.abit.service.Singleton.currentLabel import ch.dissem.apps.abit.service.Singleton.currentLabel
import ch.dissem.apps.abit.util.preferences import ch.dissem.apps.abit.util.preferences
import ch.dissem.bitmessage.entity.Conversation
import ch.dissem.bitmessage.entity.valueobject.Label import ch.dissem.bitmessage.entity.valueobject.Label
import ch.dissem.bitmessage.utils.ConversationService import ch.dissem.bitmessage.utils.ConversationService
import com.h6ah4i.android.widget.advrecyclerview.animator.SwipeDismissItemAnimator
import com.h6ah4i.android.widget.advrecyclerview.decoration.SimpleListDividerDecorator
import com.h6ah4i.android.widget.advrecyclerview.swipeable.RecyclerViewSwipeManager
import com.h6ah4i.android.widget.advrecyclerview.touchguard.RecyclerViewTouchActionGuardManager
import com.h6ah4i.android.widget.advrecyclerview.utils.WrapperAdapterUtils
import io.github.kobakei.materialfabspeeddial.FabSpeedDialMenu import io.github.kobakei.materialfabspeeddial.FabSpeedDialMenu
import io.reactivex.disposables.Disposable
import kotlinx.android.synthetic.main.fragment_message_list.* import kotlinx.android.synthetic.main.fragment_message_list.*
import org.jetbrains.anko.cancelButton import org.jetbrains.anko.*
import org.jetbrains.anko.doAsync
import org.jetbrains.anko.support.v4.alert
import org.jetbrains.anko.support.v4.onUiThread
import org.jetbrains.anko.uiThread
import java.util.* import java.util.*
private const val PAGE_SIZE = 15 private const val PAGE_SIZE = 15
@ -70,12 +63,9 @@ class ConversationListFragment : Fragment(), ListHolder<Label> {
private var layoutManager: LinearLayoutManager? = null private var layoutManager: LinearLayoutManager? = null
private var swipeableConversationAdapter: SwipeableConversationAdapter? = null private var swipeableConversationAdapter: SwipeableConversationAdapter? = null
private var wrappedAdapter: RecyclerView.Adapter<*>? = null
private var recyclerViewSwipeManager: RecyclerViewSwipeManager? = null
private var recyclerViewTouchActionGuardManager: RecyclerViewTouchActionGuardManager? = null
private val recyclerViewOnScrollListener = object : OnScrollListener() { private val recyclerViewOnScrollListener = object : OnScrollListener() {
override fun onScrolled(recyclerView: RecyclerView?, dx: Int, dy: Int) { override fun onScrolled(recyclerView: RecyclerView, dx: Int, dy: Int) {
layoutManager?.let { layoutManager -> layoutManager?.let { layoutManager ->
val visibleItemCount = layoutManager.childCount val visibleItemCount = layoutManager.childCount
val totalItemCount = layoutManager.itemCount val totalItemCount = layoutManager.itemCount
@ -98,6 +88,13 @@ class ConversationListFragment : Fragment(), ListHolder<Label> {
private lateinit var conversationService: ConversationService private lateinit var conversationService: ConversationService
private var activateOnItemClick: Boolean = false private var activateOnItemClick: Boolean = false
private var subscription: Disposable? = null
override fun setActivateOnItemClick(activateOnItemClick: Boolean) {
swipeableConversationAdapter?.activateOnItemClick = activateOnItemClick
this.activateOnItemClick = activateOnItemClick
}
private val backStack = Stack<Label>() private val backStack = Stack<Label>()
fun loadMoreItems() { fun loadMoreItems() {
@ -112,7 +109,7 @@ class ConversationListFragment : Fragment(), ListHolder<Label> {
) )
conversationIds.forEach { conversationId -> conversationIds.forEach { conversationId ->
val conversation = conversationService.getConversation(conversationId) val conversation = conversationService.getConversation(conversationId)
onUiThread { uiThread {
messageAdapter.add(conversation) messageAdapter.add(conversation)
} }
} }
@ -135,12 +132,12 @@ class ConversationListFragment : Fragment(), ListHolder<Label> {
messageRepo = Singleton.getMessageRepository(activity) messageRepo = Singleton.getMessageRepository(activity)
conversationService = Singleton.getConversationService(activity) conversationService = Singleton.getConversationService(activity)
currentLabel.addObserver(this) { new -> doUpdateList(new) } subscription = currentLabel.subscribe { new -> doUpdateList(new) }
doUpdateList(currentLabel.value) doUpdateList(currentLabel.value)
} }
override fun onPause() { override fun onPause() {
currentLabel.removeObserver(this) subscription?.dispose()
super.onPause() super.onPause()
} }
@ -158,7 +155,7 @@ class ConversationListFragment : Fragment(), ListHolder<Label> {
// I'm not yet sure if it's a good idea in conversation views, so it's off for now // I'm not yet sure if it's a good idea in conversation views, so it's off for now
deleteAllMenuItem?.isVisible = false deleteAllMenuItem?.isVisible = false
mainActivity?.apply { MainActivity.apply {
if ("archive" == label.toString()) { if ("archive" == label.toString()) {
updateTitle(getString(R.string.archive)) updateTitle(getString(R.string.archive))
} else { } else {
@ -181,75 +178,57 @@ class ConversationListFragment : Fragment(), ListHolder<Label> {
val context = context ?: throw IllegalStateException("No context available") val context = context ?: throw IllegalStateException("No context available")
layoutManager = LinearLayoutManager(context, LinearLayoutManager.VERTICAL, false) val listener = object : EventListener {
override fun onItemDeleted(position: Int) {
// touch guard manager (this class is required to suppress scrolling while swipe-dismiss swipeableConversationAdapter?.getItem(position)?.let { item ->
// animation is running)
val touchActionGuardManager = RecyclerViewTouchActionGuardManager().apply {
setInterceptVerticalScrollingWhileAnimationRunning(true)
isEnabled = true
}
// swipe manager
val swipeManager = RecyclerViewSwipeManager()
//swipeableConversationAdapter
val adapter = SwipeableConversationAdapter(context).apply {
setActivateOnItemClick(activateOnItemClick)
}
adapter.eventListener = object : SwipeableConversationAdapter.EventListener {
override fun onItemDeleted(item: Conversation) {
item.messages.forEach { item.messages.forEach {
Singleton.labeler.delete(it) Singleton.labeler.delete(it)
messageRepo.save(it) messageRepo.save(it)
} }
} }
override fun onItemArchived(item: Conversation) { swipeableConversationAdapter?.removeAt(position)
item.messages.forEach { Singleton.labeler.archive(it) }
} }
override fun onItemViewClicked(v: View?) { override fun onItemArchived(position: Int) {
val position = recycler_view.getChildAdapterPosition(v) swipeableConversationAdapter?.getItem(position)?.let { item ->
adapter.setSelectedPosition(position) item.messages.forEach {
Singleton.labeler.archive(it)
messageRepo.save(it)
}
}
swipeableConversationAdapter?.removeAt(position)
}
override fun onItemSelected(position: Int) {
swipeableConversationAdapter?.selectedPosition = position
if (position != RecyclerView.NO_POSITION) { if (position != RecyclerView.NO_POSITION) {
MainActivity.apply { onItemSelected(adapter.getItem(position)) } swipeableConversationAdapter?.getItem(position)?.let { item ->
MainActivity.apply { onItemSelected(item) }
} }
} }
} }
}
// wrap for swiping layoutManager = LinearLayoutManager(context, RecyclerView.VERTICAL, false)
wrappedAdapter = swipeManager.createWrappedAdapter(adapter)
val animator = SwipeDismissItemAnimator()
// Change animations are enabled by default since support-v7-recyclerview v22.
// Disable the change animation in order to make turning back animation of swiped item
// works properly.
animator.supportsChangeAnimations = false
recycler_view.layoutManager = layoutManager recycler_view.layoutManager = layoutManager
recycler_view.adapter = wrappedAdapter // requires *wrapped* swipeableConversationAdapter swipeableConversationAdapter = SwipeableConversationAdapter(context).apply {
recycler_view.itemAnimator = animator activateOnItemClick = this@ConversationListFragment.activateOnItemClick
eventListener = listener
}
recycler_view.adapter = swipeableConversationAdapter
recycler_view.addOnScrollListener(recyclerViewOnScrollListener) recycler_view.addOnScrollListener(recyclerViewOnScrollListener)
recycler_view.addItemDecoration( val dirs = when (currentLabel.value?.type) {
SimpleListDividerDecorator( Label.Type.TRASH -> ItemTouchHelper.LEFT
ContextCompat.getDrawable(context, R.drawable.list_divider_h), true else -> ItemTouchHelper.LEFT + ItemTouchHelper.RIGHT
) }
)
// NOTE: val swipeHandler = SwipeToDeleteCallback(context, dirs, listener)
// The initialization order is very important! This order determines the priority of
// touch event handling.
//
// priority: TouchActionGuard > Swipe > DragAndDrop
touchActionGuardManager.attachRecyclerView(recycler_view)
swipeManager.attachRecyclerView(recycler_view)
recyclerViewTouchActionGuardManager = touchActionGuardManager val itemTouchHelper = ItemTouchHelper(swipeHandler)
recyclerViewSwipeManager = swipeManager itemTouchHelper.attachToRecyclerView(recycler_view)
swipeableConversationAdapter = adapter
// FIXME Singleton.updateMessageListAdapterInListener(adapter) // FIXME Singleton.updateMessageListAdapterInListener(adapter)
} }
@ -287,18 +266,6 @@ class ConversationListFragment : Fragment(), ListHolder<Label> {
} }
override fun onDestroyView() { override fun onDestroyView() {
recyclerViewSwipeManager?.release()
recyclerViewSwipeManager = null
recyclerViewTouchActionGuardManager?.release()
recyclerViewTouchActionGuardManager = null
recycler_view.itemAnimator = null
recycler_view.adapter = null
wrappedAdapter?.let { WrapperAdapterUtils.releaseAll(it) }
wrappedAdapter = null
swipeableConversationAdapter = null swipeableConversationAdapter = null
layoutManager = null layoutManager = null
@ -324,9 +291,10 @@ class ConversationListFragment : Fragment(), ListHolder<Label> {
} }
R.id.delete_all -> { R.id.delete_all -> {
currentLabel.value?.let { label -> currentLabel.value?.let { label ->
context?.apply {
alert( alert(
title = R.string.delete_all_messages_in_list, R.string.delete_all_messages_in_list,
message = R.string.delete_all_messages_in_list_ask R.string.delete_all_messages_in_list_ask
) { ) {
positiveButton(R.string.delete) { positiveButton(R.string.delete) {
deleteAllMessages(label) deleteAllMessages(label)
@ -334,6 +302,7 @@ class ConversationListFragment : Fragment(), ListHolder<Label> {
cancelButton { } cancelButton { }
}.show() }.show()
} }
}
return true return true
} }
else -> return false else -> return false
@ -351,18 +320,13 @@ class ConversationListFragment : Fragment(), ListHolder<Label> {
} }
override fun updateList(label: Label) { override fun updateList(label: Label) {
currentLabel.value = label currentLabel.onNext(label)
}
override fun setActivateOnItemClick(activateOnItemClick: Boolean) {
swipeableConversationAdapter?.setActivateOnItemClick(activateOnItemClick)
this.activateOnItemClick = activateOnItemClick
} }
override fun showPreviousList() = if (backStack.isEmpty()) { override fun showPreviousList() = if (backStack.isEmpty()) {
false false
} else { } else {
currentLabel.value = backStack.pop() currentLabel.onNext(backStack.pop())
true true
} }
} }

View File

@ -19,7 +19,7 @@ package ch.dissem.apps.abit
import android.app.Activity import android.app.Activity
import android.net.Uri import android.net.Uri
import android.os.Bundle import android.os.Bundle
import android.support.v7.app.AppCompatActivity import androidx.appcompat.app.AppCompatActivity
import android.util.Base64 import android.util.Base64
import android.util.Base64.URL_SAFE import android.util.Base64.URL_SAFE
import android.widget.Button import android.widget.Button

View File

@ -2,8 +2,8 @@ package ch.dissem.apps.abit
import android.content.Intent import android.content.Intent
import android.os.Bundle import android.os.Bundle
import android.support.v4.app.NavUtils import androidx.core.app.NavUtils
import android.support.v7.app.AppCompatActivity import androidx.appcompat.app.AppCompatActivity
import android.view.MenuItem import android.view.MenuItem
import com.mikepenz.materialize.MaterializeBuilder import com.mikepenz.materialize.MaterializeBuilder
import kotlinx.android.synthetic.main.scrolling_toolbar_layout.* import kotlinx.android.synthetic.main.scrolling_toolbar_layout.*

View File

@ -18,7 +18,7 @@ package ch.dissem.apps.abit
import android.graphics.* import android.graphics.*
import android.graphics.drawable.Drawable import android.graphics.drawable.Drawable
import android.support.annotation.ColorInt import androidx.annotation.ColorInt
import android.text.TextPaint import android.text.TextPaint
import ch.dissem.bitmessage.entity.BitmessageAddress import ch.dissem.bitmessage.entity.BitmessageAddress
import org.jetbrains.anko.collections.forEachWithIndex import org.jetbrains.anko.collections.forEachWithIndex
@ -68,8 +68,8 @@ class Identicon(input: BitmessageAddress) : Drawable() {
} }
override fun draw(canvas: Canvas) { override fun draw(canvas: Canvas) {
val width = canvas.width.toFloat() val width = bounds.width().toFloat()
val height = canvas.height.toFloat() val height = bounds.height().toFloat()
draw(canvas, 0f, 0f, width, height) draw(canvas, 0f, 0f, width, height)
} }
@ -124,11 +124,11 @@ class MultiIdenticon(input: List<BitmessageAddress>, @ColorInt private val backg
color = backgroundColor color = backgroundColor
} }
private val identicons = input.sortedBy { it.isChan }.map { Identicon(it) }.take(4) private val identicons = input.asSequence().sortedBy { it.isChan }.map { Identicon(it) }.take(4).toList()
override fun draw(canvas: Canvas) { override fun draw(canvas: Canvas) {
val width = canvas.width.toFloat() val width = bounds.width().toFloat()
val height = canvas.height.toFloat() val height = bounds.height().toFloat()
when (identicons.size) { when (identicons.size) {
0 -> canvas.drawCircle(width / 2, height / 2, width / 2, paint) 0 -> canvas.drawCircle(width / 2, height / 2, width / 2, paint)

View File

@ -16,19 +16,18 @@
package ch.dissem.apps.abit package ch.dissem.apps.abit
import android.app.Fragment
import android.os.Bundle import android.os.Bundle
import android.support.v4.content.ContextCompat
import android.support.v7.widget.LinearLayoutManager
import android.support.v7.widget.RecyclerView
import android.view.LayoutInflater import android.view.LayoutInflater
import android.view.View import android.view.View
import android.view.ViewGroup import android.view.ViewGroup
import android.widget.Button import android.widget.Button
import androidx.fragment.app.Fragment
import androidx.recyclerview.widget.DividerItemDecoration
import androidx.recyclerview.widget.LinearLayoutManager
import androidx.recyclerview.widget.RecyclerView
import ch.dissem.apps.abit.adapter.AddressSelectorAdapter import ch.dissem.apps.abit.adapter.AddressSelectorAdapter
import ch.dissem.apps.abit.service.Singleton import ch.dissem.apps.abit.service.Singleton
import ch.dissem.bitmessage.wif.WifImporter import ch.dissem.bitmessage.wif.WifImporter
import com.h6ah4i.android.widget.advrecyclerview.decoration.SimpleListDividerDecorator
import org.ini4j.InvalidFileFormatException import org.ini4j.InvalidFileFormatException
import org.jetbrains.anko.longToast import org.jetbrains.anko.longToast
@ -47,34 +46,31 @@ class ImportIdentitiesFragment : Fragment() {
inflater.inflate(R.layout.fragment_import_select_identities, container, false) inflater.inflate(R.layout.fragment_import_select_identities, container, false)
override fun onViewCreated(view: View, savedInstanceState: Bundle?) { override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
val ctx = activity ?: throw IllegalStateException("No activity available")
super.onViewCreated(view, savedInstanceState) super.onViewCreated(view, savedInstanceState)
val wifData = arguments.getString(WIF_DATA) val wifData = arguments?.getString(WIF_DATA) ?: throw IllegalStateException("No WIF data")
val bmc = Singleton.getBitmessageContext(activity) val bmc = Singleton.getBitmessageContext(ctx)
try { try {
importer = WifImporter(bmc, wifData) importer = WifImporter(bmc, wifData)
} catch (e: InvalidFileFormatException) { } catch (e: InvalidFileFormatException) {
longToast(R.string.invalid_wif_file) ctx.longToast(R.string.invalid_wif_file)
activity.finish() ctx.finish()
return return
} }
adapter = AddressSelectorAdapter(importer.getIdentities()) adapter = AddressSelectorAdapter(importer.getIdentities())
val layoutManager = LinearLayoutManager( val layoutManager = LinearLayoutManager(
activity, activity,
LinearLayoutManager.VERTICAL, RecyclerView.VERTICAL,
false false
) )
val recyclerView = view.findViewById<RecyclerView>(R.id.recycler_view) val recyclerView = view.findViewById<RecyclerView>(R.id.recycler_view)
recyclerView.layoutManager = layoutManager recyclerView.layoutManager = layoutManager
recyclerView.adapter = adapter recyclerView.adapter = adapter
recyclerView.addItemDecoration( recyclerView.addItemDecoration(DividerItemDecoration(ctx, DividerItemDecoration.HORIZONTAL))
SimpleListDividerDecorator(
ContextCompat.getDrawable(activity, R.drawable.list_divider_h), true
)
)
view.findViewById<Button>(R.id.finish).setOnClickListener { view.findViewById<Button>(R.id.finish).setOnClickListener {
importer.importAll(adapter.selected) importer.importAll(adapter.selected)
@ -83,7 +79,7 @@ class ImportIdentitiesFragment : Fragment() {
addIdentityEntry(selected) addIdentityEntry(selected)
} }
} }
activity.finish() ctx.finish()
} }
} }

View File

@ -17,6 +17,7 @@
package ch.dissem.apps.abit package ch.dissem.apps.abit
import android.os.Bundle import android.os.Bundle
import androidx.fragment.app.transaction
/** /**
* @author Christian Basler * @author Christian Basler
@ -29,19 +30,20 @@ class ImportIdentityActivity : DetailActivity() {
val wifData: String? = savedInstanceState?.getString(ImportIdentitiesFragment.WIF_DATA) val wifData: String? = savedInstanceState?.getString(ImportIdentitiesFragment.WIF_DATA)
if (wifData == null) { if (wifData == null) {
fragmentManager.beginTransaction() supportFragmentManager.transaction {
.replace(R.id.content, InputWifFragment()) replace(R.id.content, InputWifFragment())
.commit() }
} else { } else {
val bundle = Bundle() val bundle = Bundle()
bundle.putString(ImportIdentitiesFragment.WIF_DATA, wifData) bundle.putString(ImportIdentitiesFragment.WIF_DATA, wifData)
val fragment = ImportIdentitiesFragment() val fragment = ImportIdentitiesFragment().apply {
fragment.arguments = bundle arguments = bundle
}
fragmentManager.beginTransaction() supportFragmentManager.transaction {
.replace(R.id.content, fragment) replace(R.id.content, fragment)
.commit() }
} }
} }

View File

@ -16,10 +16,11 @@
package ch.dissem.apps.abit package ch.dissem.apps.abit
import android.app.Fragment
import android.os.Bundle import android.os.Bundle
import android.view.* import android.view.*
import android.widget.Toast import android.widget.Toast
import androidx.fragment.app.Fragment
import androidx.fragment.app.transaction
import com.github.angads25.filepicker.model.DialogConfigs import com.github.angads25.filepicker.model.DialogConfigs
import com.github.angads25.filepicker.model.DialogProperties import com.github.angads25.filepicker.model.DialogProperties
import com.github.angads25.filepicker.view.FilePickerDialog import com.github.angads25.filepicker.view.FilePickerDialog
@ -42,7 +43,7 @@ class InputWifFragment : Fragment() {
override fun onCreateView(inflater: LayoutInflater, container: ViewGroup?, savedInstanceState: Bundle?): View = override fun onCreateView(inflater: LayoutInflater, container: ViewGroup?, savedInstanceState: Bundle?): View =
inflater.inflate(R.layout.fragment_import_input, container, false) inflater.inflate(R.layout.fragment_import_input, container, false)
override fun onViewCreated(view: View?, savedInstanceState: Bundle?) { override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
super.onViewCreated(view, savedInstanceState) super.onViewCreated(view, savedInstanceState)
next.setOnClickListener { next.setOnClickListener {
val bundle = Bundle() val bundle = Bundle()
@ -52,9 +53,9 @@ class InputWifFragment : Fragment() {
arguments = bundle arguments = bundle
} }
fragmentManager.beginTransaction() fragmentManager?.transaction {
.replace(R.id.content, fragment) replace(R.id.content, fragment)
.commit() }
} }
} }

View File

@ -20,11 +20,12 @@ import android.content.Intent
import android.graphics.Canvas import android.graphics.Canvas
import android.graphics.Paint import android.graphics.Paint
import android.os.Bundle import android.os.Bundle
import android.support.annotation.DrawableRes
import android.support.v4.app.Fragment
import android.support.v7.app.AppCompatActivity
import android.support.v7.widget.Toolbar
import android.view.View import android.view.View
import androidx.annotation.DrawableRes
import androidx.appcompat.app.AppCompatActivity
import androidx.appcompat.widget.Toolbar
import androidx.fragment.app.Fragment
import androidx.fragment.app.transaction
import ch.dissem.apps.abit.drawer.ProfileImageListener import ch.dissem.apps.abit.drawer.ProfileImageListener
import ch.dissem.apps.abit.drawer.ProfileSelectionListener import ch.dissem.apps.abit.drawer.ProfileSelectionListener
import ch.dissem.apps.abit.listener.ListSelectionListener import ch.dissem.apps.abit.listener.ListSelectionListener
@ -32,7 +33,10 @@ import ch.dissem.apps.abit.repository.AndroidLabelRepository.Companion.LABEL_ARC
import ch.dissem.apps.abit.repository.AndroidMessageRepository import ch.dissem.apps.abit.repository.AndroidMessageRepository
import ch.dissem.apps.abit.service.Singleton import ch.dissem.apps.abit.service.Singleton
import ch.dissem.apps.abit.service.Singleton.currentLabel import ch.dissem.apps.abit.service.Singleton.currentLabel
import ch.dissem.apps.abit.util.* import ch.dissem.apps.abit.util.getColor
import ch.dissem.apps.abit.util.getIcon
import ch.dissem.apps.abit.util.network
import ch.dissem.apps.abit.util.preferences
import ch.dissem.bitmessage.BitmessageContext import ch.dissem.bitmessage.BitmessageContext
import ch.dissem.bitmessage.entity.BitmessageAddress import ch.dissem.bitmessage.entity.BitmessageAddress
import ch.dissem.bitmessage.entity.Conversation import ch.dissem.bitmessage.entity.Conversation
@ -51,6 +55,7 @@ import com.mikepenz.materialdrawer.model.interfaces.IProfile
import com.mikepenz.materialdrawer.model.interfaces.Nameable import com.mikepenz.materialdrawer.model.interfaces.Nameable
import io.github.kobakei.materialfabspeeddial.FabSpeedDial import io.github.kobakei.materialfabspeeddial.FabSpeedDial
import io.github.kobakei.materialfabspeeddial.FabSpeedDialMenu import io.github.kobakei.materialfabspeeddial.FabSpeedDialMenu
import io.reactivex.disposables.Disposable
import kotlinx.android.synthetic.main.activity_main.* import kotlinx.android.synthetic.main.activity_main.*
import org.jetbrains.anko.doAsync import org.jetbrains.anko.doAsync
import org.jetbrains.anko.uiThread import org.jetbrains.anko.uiThread
@ -92,6 +97,8 @@ class MainActivity : AppCompatActivity(), ListSelectionListener<Serializable> {
var hasDetailPane: Boolean = false var hasDetailPane: Boolean = false
private set private set
private var subscription: Disposable? = null
private lateinit var bmc: BitmessageContext private lateinit var bmc: BitmessageContext
private lateinit var messageRepo: AndroidMessageRepository private lateinit var messageRepo: AndroidMessageRepository
private lateinit var accountHeader: AccountHeader private lateinit var accountHeader: AccountHeader
@ -294,11 +301,11 @@ class MainActivity : AppCompatActivity(), ListSelectionListener<Serializable> {
uiThread { uiThread {
if (intent.hasExtra(EXTRA_SHOW_LABEL)) { if (intent.hasExtra(EXTRA_SHOW_LABEL)) {
currentLabel.value = intent.getSerializableExtra(EXTRA_SHOW_LABEL) as Label currentLabel.onNext(intent.getSerializableExtra(EXTRA_SHOW_LABEL) as Label)
} else if (currentLabel.value == null) { } else if (currentLabel.value == null) {
currentLabel.value = labels[0] currentLabel.onNext(labels[0])
} }
for (label in labels) { for (label in labels) {
addLabelEntry(label) addLabelEntry(label)
} }
@ -322,7 +329,7 @@ class MainActivity : AppCompatActivity(), ListSelectionListener<Serializable> {
val itemList = supportFragmentManager.findFragmentById(R.id.item_list) val itemList = supportFragmentManager.findFragmentById(R.id.item_list)
val tag = item.tag val tag = item.tag
if (tag is Label) { if (tag is Label) {
currentLabel.value = tag currentLabel.onNext(tag)
if (tag.type == Label.Type.INBOX || tag == LABEL_ARCHIVE) { if (tag.type == Label.Type.INBOX || tag == LABEL_ARCHIVE) {
if (itemList !is ConversationListFragment) { if (itemList !is ConversationListFragment) {
changeList(ConversationListFragment()) changeList(ConversationListFragment())
@ -344,11 +351,10 @@ class MainActivity : AppCompatActivity(), ListSelectionListener<Serializable> {
return false return false
} }
R.string.settings -> { R.string.settings -> {
supportFragmentManager supportFragmentManager?.transaction {
.beginTransaction() replace(R.id.item_list, SettingsFragment())
.replace(R.id.item_list, SettingsFragment()) addToBackStack(null)
.addToBackStack(null) }
.commit()
return false return false
} }
R.string.full_node -> return true R.string.full_node -> return true
@ -363,9 +369,9 @@ class MainActivity : AppCompatActivity(), ListSelectionListener<Serializable> {
network.enableNode(false) network.enableNode(false)
updateUnread() updateUnread()
Singleton.getMessageListener(this).resetNotification() Singleton.getMessageListener(this).resetNotification()
currentLabel.addObserver(this) { label -> subscription = currentLabel.subscribe { label ->
if (label != null && label.id is Long) { if (label.id is Long) {
drawer.setSelection(label.id as Long) drawer.setSelection(label.id as Long, false)
} }
} }
active = true active = true
@ -373,7 +379,7 @@ class MainActivity : AppCompatActivity(), ListSelectionListener<Serializable> {
} }
override fun onPause() { override fun onPause() {
currentLabel.removeObserver(this) subscription?.dispose()
super.onPause() super.onPause()
active = false active = false
} }
@ -537,9 +543,8 @@ class MainActivity : AppCompatActivity(), ListSelectionListener<Serializable> {
fun initFab(@DrawableRes drawableRes: Int, menu: FabSpeedDialMenu): FabSpeedDial { fun initFab(@DrawableRes drawableRes: Int, menu: FabSpeedDialMenu): FabSpeedDial {
val fab = floatingActionButton ?: throw IllegalStateException("Fab must not be null") val fab = floatingActionButton ?: throw IllegalStateException("Fab must not be null")
fab.hide()
fab.removeAllOnMenuItemClickListeners() fab.removeAllOnMenuItemClickListeners()
fab.show()
fab.closeMenu()
val mainFab = fab.mainFab val mainFab = fab.mainFab
mainFab.setImageResource(drawableRes) mainFab.setImageResource(drawableRes)
fab.setMenu(menu) fab.setMenu(menu)
@ -551,6 +556,8 @@ class MainActivity : AppCompatActivity(), ListSelectionListener<Serializable> {
mainFab.setImageResource(drawableRes) mainFab.setImageResource(drawableRes)
} }
} }
fab.show()
fab.closeMenu()
return fab return fab
} }

View File

@ -2,7 +2,7 @@ package ch.dissem.apps.abit
import android.content.Intent import android.content.Intent
import android.os.Bundle import android.os.Bundle
import android.support.v4.app.NavUtils import androidx.core.app.NavUtils
import android.view.MenuItem import android.view.MenuItem
import ch.dissem.bitmessage.entity.Plaintext import ch.dissem.bitmessage.entity.Plaintext

View File

@ -19,11 +19,11 @@ package ch.dissem.apps.abit
import android.content.Context import android.content.Context
import android.content.Intent import android.content.Intent
import android.os.Bundle import android.os.Bundle
import android.support.annotation.IdRes import androidx.annotation.IdRes
import android.support.v4.app.Fragment import androidx.fragment.app.Fragment
import android.support.v7.widget.GridLayoutManager import androidx.recyclerview.widget.GridLayoutManager
import android.support.v7.widget.LinearLayoutManager import androidx.recyclerview.widget.LinearLayoutManager
import android.support.v7.widget.RecyclerView import androidx.recyclerview.widget.RecyclerView
import android.text.util.Linkify import android.text.util.Linkify
import android.text.util.Linkify.WEB_URLS import android.text.util.Linkify.WEB_URLS
import android.view.* import android.view.*

View File

@ -19,33 +19,28 @@ package ch.dissem.apps.abit
import android.content.Intent import android.content.Intent
import android.os.Bundle import android.os.Bundle
import android.support.v4.app.Fragment import androidx.fragment.app.Fragment
import android.support.v4.content.ContextCompat import androidx.recyclerview.widget.ItemTouchHelper
import android.support.v7.widget.LinearLayoutManager import androidx.recyclerview.widget.LinearLayoutManager
import android.support.v7.widget.RecyclerView import androidx.recyclerview.widget.RecyclerView
import android.support.v7.widget.RecyclerView.OnScrollListener import androidx.recyclerview.widget.RecyclerView.OnScrollListener
import android.view.* import android.view.*
import android.widget.Toast import android.widget.Toast
import ch.dissem.apps.abit.ComposeMessageActivity.Companion.EXTRA_BROADCAST import ch.dissem.apps.abit.ComposeMessageActivity.Companion.EXTRA_BROADCAST
import ch.dissem.apps.abit.ComposeMessageActivity.Companion.EXTRA_IDENTITY import ch.dissem.apps.abit.ComposeMessageActivity.Companion.EXTRA_IDENTITY
import ch.dissem.apps.abit.adapter.EventListener
import ch.dissem.apps.abit.adapter.SwipeToDeleteCallback
import ch.dissem.apps.abit.adapter.SwipeableMessageAdapter import ch.dissem.apps.abit.adapter.SwipeableMessageAdapter
import ch.dissem.apps.abit.listener.ListSelectionListener import ch.dissem.apps.abit.listener.ListSelectionListener
import ch.dissem.apps.abit.repository.AndroidMessageRepository import ch.dissem.apps.abit.repository.AndroidMessageRepository
import ch.dissem.apps.abit.service.Singleton import ch.dissem.apps.abit.service.Singleton
import ch.dissem.apps.abit.service.Singleton.currentLabel import ch.dissem.apps.abit.service.Singleton.currentLabel
import ch.dissem.apps.abit.util.preferences import ch.dissem.apps.abit.util.preferences
import ch.dissem.bitmessage.entity.Plaintext
import ch.dissem.bitmessage.entity.valueobject.Label import ch.dissem.bitmessage.entity.valueobject.Label
import com.h6ah4i.android.widget.advrecyclerview.animator.SwipeDismissItemAnimator
import com.h6ah4i.android.widget.advrecyclerview.decoration.SimpleListDividerDecorator
import com.h6ah4i.android.widget.advrecyclerview.swipeable.RecyclerViewSwipeManager
import com.h6ah4i.android.widget.advrecyclerview.touchguard.RecyclerViewTouchActionGuardManager
import com.h6ah4i.android.widget.advrecyclerview.utils.WrapperAdapterUtils
import io.github.kobakei.materialfabspeeddial.FabSpeedDialMenu import io.github.kobakei.materialfabspeeddial.FabSpeedDialMenu
import io.reactivex.disposables.Disposable
import kotlinx.android.synthetic.main.fragment_message_list.* import kotlinx.android.synthetic.main.fragment_message_list.*
import org.jetbrains.anko.* import org.jetbrains.anko.*
import org.jetbrains.anko.support.v4.alert
import org.jetbrains.anko.support.v4.onUiThread
import java.util.* import java.util.*
private const val PAGE_SIZE = 15 private const val PAGE_SIZE = 15
@ -65,21 +60,20 @@ class MessageListFragment : Fragment(), ListHolder<Label> {
private var isLoading = false private var isLoading = false
private var isLastPage = false private var isLastPage = false
private var subscription: Disposable? = null
private var layoutManager: LinearLayoutManager? = null private var layoutManager: LinearLayoutManager? = null
private var swipeableMessageAdapter: SwipeableMessageAdapter? = null private var swipeableMessageAdapter: SwipeableMessageAdapter? = null
private var wrappedAdapter: RecyclerView.Adapter<*>? = null
private var recyclerViewSwipeManager: RecyclerViewSwipeManager? = null
private var recyclerViewTouchActionGuardManager: RecyclerViewTouchActionGuardManager? = null
private val recyclerViewOnScrollListener = object : OnScrollListener() { private val recyclerViewOnScrollListener = object : OnScrollListener() {
override fun onScrolled(recyclerView: RecyclerView?, dx: Int, dy: Int) { override fun onScrolled(recyclerView: RecyclerView, dx: Int, dy: Int) {
layoutManager?.let { layoutManager -> layoutManager?.let { layoutManager ->
val visibleItemCount = layoutManager.childCount val visibleItemCount = layoutManager.childCount
val totalItemCount = layoutManager.itemCount val totalItemCount = layoutManager.itemCount
val firstVisibleItemPosition = layoutManager.findFirstVisibleItemPosition() val firstVisibleItemPosition = layoutManager.findFirstVisibleItemPosition()
if (!isLoading && !isLastPage) { if (!isLoading && !isLastPage) {
if (visibleItemCount + firstVisibleItemPosition >= totalItemCount - 5 if (visibleItemCount + firstVisibleItemPosition >= totalItemCount - PAGE_SIZE
&& firstVisibleItemPosition >= 0 && firstVisibleItemPosition >= 0
) { ) {
loadMoreItems() loadMoreItems()
@ -94,6 +88,11 @@ class MessageListFragment : Fragment(), ListHolder<Label> {
private lateinit var messageRepo: AndroidMessageRepository private lateinit var messageRepo: AndroidMessageRepository
private var activateOnItemClick: Boolean = false private var activateOnItemClick: Boolean = false
override fun setActivateOnItemClick(activateOnItemClick: Boolean) {
swipeableMessageAdapter?.activateOnItemClick = activateOnItemClick
this.activateOnItemClick = activateOnItemClick
}
private val backStack = Stack<Label>() private val backStack = Stack<Label>()
fun loadMoreItems() { fun loadMoreItems() {
@ -107,7 +106,7 @@ class MessageListFragment : Fragment(), ListHolder<Label> {
PAGE_SIZE, PAGE_SIZE,
context?.preferences?.separateIdentities == true && label?.type != Label.Type.BROADCAST context?.preferences?.separateIdentities == true && label?.type != Label.Type.BROADCAST
) )
onUiThread { uiThread {
messageAdapter.addAll(messages) messageAdapter.addAll(messages)
isLoading = false isLoading = false
isLastPage = messages.size < PAGE_SIZE isLastPage = messages.size < PAGE_SIZE
@ -128,12 +127,12 @@ class MessageListFragment : Fragment(), ListHolder<Label> {
initFab(activity) initFab(activity)
messageRepo = Singleton.getMessageRepository(activity) messageRepo = Singleton.getMessageRepository(activity)
currentLabel.addObserver(this) { new -> doUpdateList(new) } subscription = currentLabel.subscribe { new -> doUpdateList(new) }
doUpdateList(currentLabel.value) doUpdateList(currentLabel.value)
} }
override fun onPause() { override fun onPause() {
currentLabel.removeObserver(this) subscription?.dispose()
super.onPause() super.onPause()
} }
@ -151,7 +150,7 @@ class MessageListFragment : Fragment(), ListHolder<Label> {
return return
} }
menuItem.isVisible = label.type == Label.Type.TRASH menuItem.isVisible = label.type == Label.Type.TRASH
mainActivity?.apply { MainActivity.apply {
if ("archive" == label.toString()) { if ("archive" == label.toString()) {
updateTitle(getString(R.string.archive)) updateTitle(getString(R.string.archive))
} else { } else {
@ -176,81 +175,37 @@ class MessageListFragment : Fragment(), ListHolder<Label> {
val context = context ?: throw IllegalStateException("No context available") val context = context ?: throw IllegalStateException("No context available")
layoutManager = LinearLayoutManager(context, LinearLayoutManager.VERTICAL, false) layoutManager = LinearLayoutManager(context, RecyclerView.VERTICAL, false)
// touch guard manager (this class is required to suppress scrolling while swipe-dismiss
// animation is running)
val touchActionGuardManager = RecyclerViewTouchActionGuardManager().apply {
setInterceptVerticalScrollingWhileAnimationRunning(true)
isEnabled = true
}
// swipe manager
val swipeManager = RecyclerViewSwipeManager()
//swipeableMessageAdapter
val adapter = SwipeableMessageAdapter().apply {
setActivateOnItemClick(activateOnItemClick)
}
adapter.eventListener = object : SwipeableMessageAdapter.EventListener {
override fun onItemDeleted(item: Plaintext) {
if (MessageDetailFragment.isInTrash(item)) {
Singleton.labeler.delete(item)
messageRepo.remove(item)
} else {
Singleton.labeler.delete(item)
messageRepo.save(item)
}
}
override fun onItemArchived(item: Plaintext) {
Singleton.labeler.archive(item)
}
override fun onItemViewClicked(v: View?) {
val position = recycler_view.getChildAdapterPosition(v)
adapter.setSelectedPosition(position)
if (position != RecyclerView.NO_POSITION) {
val item = adapter.getItem(position)
MainActivity.apply { onItemSelected(item) }
}
}
}
// wrap for swiping
wrappedAdapter = swipeManager.createWrappedAdapter(adapter)
val animator = SwipeDismissItemAnimator()
// Change animations are enabled by default since support-v7-recyclerview v22.
// Disable the change animation in order to make turning back animation of swiped item
// works properly.
animator.supportsChangeAnimations = false
recycler_view.layoutManager = layoutManager recycler_view.layoutManager = layoutManager
recycler_view.adapter = wrappedAdapter // requires *wrapped* swipeableMessageAdapter swipeableMessageAdapter = SwipeableMessageAdapter(context).apply {
recycler_view.itemAnimator = animator activateOnItemClick = this@MessageListFragment.activateOnItemClick
}
recycler_view.adapter = swipeableMessageAdapter // requires *wrapped* swipeableMessageAdapter
recycler_view.addOnScrollListener(recyclerViewOnScrollListener) recycler_view.addOnScrollListener(recyclerViewOnScrollListener)
recycler_view.addItemDecoration( val dirs = when (currentLabel.value?.type) {
SimpleListDividerDecorator( Label.Type.TRASH -> ItemTouchHelper.LEFT
ContextCompat.getDrawable(context, R.drawable.list_divider_h), true else -> ItemTouchHelper.LEFT + ItemTouchHelper.RIGHT
) }
)
// NOTE: val swipeHandler = SwipeToDeleteCallback(context, dirs, object : EventListener {
// The initialization order is very important! This order determines the priority of override fun onItemDeleted(position: Int) {
// touch event handling. context.toast("Deleted")
// }
// priority: TouchActionGuard > Swipe > DragAndDrop
touchActionGuardManager.attachRecyclerView(recycler_view)
swipeManager.attachRecyclerView(recycler_view)
recyclerViewTouchActionGuardManager = touchActionGuardManager override fun onItemArchived(position: Int) {
recyclerViewSwipeManager = swipeManager context.toast("Archived")
swipeableMessageAdapter = adapter }
Singleton.updateMessageListAdapterInListener(adapter) override fun onItemSelected(position: Int) {
context.toast("Selected")
}
})
val itemTouchHelper = ItemTouchHelper(swipeHandler)
itemTouchHelper.attachToRecyclerView(recycler_view)
// FIXME Singleton.updateMessageListAdapterInListener(adapter)
} }
private fun initFab(context: MainActivity) { private fun initFab(context: MainActivity) {
@ -286,18 +241,6 @@ class MessageListFragment : Fragment(), ListHolder<Label> {
} }
override fun onDestroyView() { override fun onDestroyView() {
recyclerViewSwipeManager?.release()
recyclerViewSwipeManager = null
recyclerViewTouchActionGuardManager?.release()
recyclerViewTouchActionGuardManager = null
recycler_view.itemAnimator = null
recycler_view.adapter = null
wrappedAdapter?.let { WrapperAdapterUtils.releaseAll(it) }
wrappedAdapter = null
swipeableMessageAdapter = null swipeableMessageAdapter = null
layoutManager = null layoutManager = null
@ -308,7 +251,7 @@ class MessageListFragment : Fragment(), ListHolder<Label> {
inflater.inflate(R.menu.message_list, menu) inflater.inflate(R.menu.message_list, menu)
emptyTrashMenuItem = menu.findItem(R.id.empty_trash) emptyTrashMenuItem = menu.findItem(R.id.empty_trash)
deleteAllMenuItem = menu.findItem(R.id.delete_all) deleteAllMenuItem = menu.findItem(R.id.delete_all)
currentLabel.value?.let { doUpdateList(it) } // currentLabel.value?.let { doUpdateList(it) }
super.onCreateOptionsMenu(menu, inflater) super.onCreateOptionsMenu(menu, inflater)
} }
@ -324,9 +267,10 @@ class MessageListFragment : Fragment(), ListHolder<Label> {
} }
R.id.delete_all -> { R.id.delete_all -> {
currentLabel.value?.let { label -> currentLabel.value?.let { label ->
context?.apply {
alert( alert(
title = R.string.delete_all_messages_in_list, R.string.delete_all_messages_in_list,
message = R.string.delete_all_messages_in_list_ask R.string.delete_all_messages_in_list_ask
) { ) {
positiveButton(R.string.delete) { positiveButton(R.string.delete) {
deleteAllMessages(label) deleteAllMessages(label)
@ -334,6 +278,7 @@ class MessageListFragment : Fragment(), ListHolder<Label> {
cancelButton { } cancelButton { }
}.show() }.show()
} }
}
return true return true
} }
else -> return false else -> return false
@ -351,18 +296,13 @@ class MessageListFragment : Fragment(), ListHolder<Label> {
} }
override fun updateList(label: Label) { override fun updateList(label: Label) {
currentLabel.value = label currentLabel.onNext(label)
}
override fun setActivateOnItemClick(activateOnItemClick: Boolean) {
swipeableMessageAdapter?.setActivateOnItemClick(activateOnItemClick)
this.activateOnItemClick = activateOnItemClick
} }
override fun showPreviousList() = if (backStack.isEmpty()) { override fun showPreviousList() = if (backStack.isEmpty()) {
false false
} else { } else {
currentLabel.value = backStack.pop() currentLabel.onNext(backStack.pop())
true true
} }
} }

View File

@ -23,16 +23,11 @@ import android.content.Intent
import android.content.ServiceConnection import android.content.ServiceConnection
import android.os.Bundle import android.os.Bundle
import android.os.IBinder import android.os.IBinder
import android.support.v4.app.Fragment
import android.support.v4.content.ContextCompat
import android.support.v4.content.FileProvider.getUriForFile
import android.support.v7.preference.Preference
import android.support.v7.preference.Preference.OnPreferenceChangeListener
import android.support.v7.preference.PreferenceFragmentCompat
import android.support.v7.preference.PreferenceScreen
import android.support.v7.preference.SwitchPreferenceCompat
import android.view.View
import android.widget.Toast import android.widget.Toast
import androidx.core.content.FileProvider.getUriForFile
import androidx.preference.Preference
import androidx.preference.PreferenceFragmentCompat
import androidx.preference.SwitchPreferenceCompat
import ch.dissem.apps.abit.service.BatchProcessorService import ch.dissem.apps.abit.service.BatchProcessorService
import ch.dissem.apps.abit.service.SimpleJob import ch.dissem.apps.abit.service.SimpleJob
import ch.dissem.apps.abit.service.Singleton import ch.dissem.apps.abit.service.Singleton
@ -43,15 +38,15 @@ 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.indeterminateProgressDialog
import org.jetbrains.anko.support.v4.startActivity import org.jetbrains.anko.startActivity
import org.jetbrains.anko.uiThread import org.jetbrains.anko.uiThread
import java.util.* import java.util.*
/** /**
* @author Christian Basler * @author Christian Basler
*/ */
class SettingsFragment : PreferenceFragmentCompat(), PreferenceFragmentCompat.OnPreferenceStartScreenCallback { class SettingsFragment : PreferenceFragmentCompat() {
override fun onCreatePreferences(savedInstanceState: Bundle?, rootKey: String?) { override fun onCreatePreferences(savedInstanceState: Bundle?, rootKey: String?) {
setPreferencesFromResource(R.xml.preferences, rootKey) setPreferencesFromResource(R.xml.preferences, rootKey)
@ -117,9 +112,9 @@ class SettingsFragment : PreferenceFragmentCompat(), PreferenceFragmentCompat.On
} }
private fun exportClickListener() = Preference.OnPreferenceClickListener { private fun exportClickListener() = Preference.OnPreferenceClickListener {
val ctx = context ?: throw IllegalStateException("No context available") val ctx = activity ?: throw IllegalStateException("No context available")
indeterminateProgressDialog(R.string.export_data_summary, R.string.export_data).apply { ctx.indeterminateProgressDialog(R.string.export_data_summary, R.string.export_data).apply {
doAsync { doAsync {
val exportDirectory = ctx.preferences.exportDirectory val exportDirectory = ctx.preferences.exportDirectory
exportDirectory.mkdirs() exportDirectory.mkdirs()
@ -152,20 +147,20 @@ class SettingsFragment : PreferenceFragmentCompat(), PreferenceFragmentCompat.On
if (activity.hasDetailPane) { if (activity.hasDetailPane) {
activity.setDetailView(StatusFragment()) activity.setDetailView(StatusFragment())
} else { } else {
startActivity<StatusActivity>() activity.startActivity<StatusActivity>()
} }
return@OnPreferenceClickListener true return@OnPreferenceClickListener true
} }
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 = activity ?: throw IllegalStateException("No context available")
when (requestCode) { when (requestCode) {
WRITE_EXPORT_REQUEST_CODE -> ctx.preferences.cleanupExportDirectory() WRITE_EXPORT_REQUEST_CODE -> ctx.preferences.cleanupExportDirectory()
READ_IMPORT_REQUEST_CODE -> { READ_IMPORT_REQUEST_CODE -> {
if (resultCode == Activity.RESULT_OK && data?.data != null) { if (resultCode == Activity.RESULT_OK && data?.data != null) {
indeterminateProgressDialog(R.string.import_data_summary, R.string.import_data).apply { ctx.indeterminateProgressDialog(R.string.import_data_summary, R.string.import_data).apply {
doAsync { doAsync {
Exports.importData(data.data, ctx) Exports.importData(data.data!!, ctx)
uiThread { uiThread {
dismiss() dismiss()
} }
@ -224,40 +219,41 @@ class SettingsFragment : PreferenceFragmentCompat(), PreferenceFragmentCompat.On
} }
private fun emulateConversationChangeListener(conversationInit: Preference?) = private fun emulateConversationChangeListener(conversationInit: Preference?) =
OnPreferenceChangeListener { _, newValue -> Preference.OnPreferenceChangeListener { _, newValue ->
conversationInit?.isEnabled = newValue as Boolean conversationInit?.isEnabled = newValue as Boolean
true true
} }
private fun connectivityChangeListener() = private fun connectivityChangeListener() =
OnPreferenceChangeListener { _, _ -> Preference.OnPreferenceChangeListener { _, _ ->
context?.network?.scheduleNodeStart() activity?.network?.scheduleNodeStart()
true true
} }
// The why-is-it-so-damn-hard-to-group-preferences section // The why-is-it-so-damn-hard-to-group-preferences section
override fun getCallbackFragment(): Fragment = this // FIXME: maybe this is once again necessary, maybe not. Test!
// override fun getCallbackFragment(): Fragment = this
override fun onPreferenceStartScreen( //
preferenceFragmentCompat: PreferenceFragmentCompat, // override fun onPreferenceStartScreen(
preferenceScreen: PreferenceScreen // preferenceFragmentCompat: PreferenceFragment,
): Boolean { // preferenceScreen: PreferenceScreen
fragmentManager?.beginTransaction()?.let { ft -> // ): Boolean {
val fragment = SettingsFragment() // fragmentManager?.beginTransaction()?.let { ft ->
fragment.arguments = Bundle().apply { // val fragment = SettingsFragment()
putString(PreferenceFragmentCompat.ARG_PREFERENCE_ROOT, preferenceScreen.key) // fragment.arguments = Bundle().apply {
} // putString(PreferenceFragment.ARG_PREFERENCE_ROOT, preferenceScreen.key)
ft.add(R.id.item_list, fragment, preferenceScreen.key) // }
ft.addToBackStack(preferenceScreen.key) // ft.add(R.id.item_list, fragment, preferenceScreen.key)
ft.commit() // ft.addToBackStack(preferenceScreen.key)
} // ft.commit()
return true // }
} // return true
// }
override fun onViewCreated(view: View, savedInstanceState: Bundle?) { //
super.onViewCreated(view, savedInstanceState) // override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
context?.let { ctx -> view.setBackgroundColor(ContextCompat.getColor(ctx, R.color.contentBackground)) } // super.onViewCreated(view, savedInstanceState)
} // context?.let { ctx -> view.setBackgroundColor(ContextCompat.getColor(ctx, R.color.contentBackground)) }
// }
// End of the why-is-it-so-damn-hard-to-group-preferences section // End of the why-is-it-so-damn-hard-to-group-preferences section
// Afterthought: here it looks so simple: https://developer.android.com/guide/topics/ui/settings.html // Afterthought: here it looks so simple: https://developer.android.com/guide/topics/ui/settings.html
// Remind me, why do we need to use PreferenceFragmentCompat? // Remind me, why do we need to use PreferenceFragmentCompat?

View File

@ -17,7 +17,7 @@
package ch.dissem.apps.abit package ch.dissem.apps.abit
import android.os.Bundle import android.os.Bundle
import android.support.v7.app.AppCompatActivity import androidx.appcompat.app.AppCompatActivity
import ch.dissem.apps.abit.service.Singleton import ch.dissem.apps.abit.service.Singleton
import com.mikepenz.materialize.MaterializeBuilder import com.mikepenz.materialize.MaterializeBuilder
import kotlinx.android.synthetic.main.activity_status.* import kotlinx.android.synthetic.main.activity_status.*

View File

@ -17,7 +17,7 @@
package ch.dissem.apps.abit package ch.dissem.apps.abit
import android.os.Bundle import android.os.Bundle
import android.support.v4.app.Fragment import androidx.fragment.app.Fragment
import android.view.LayoutInflater import android.view.LayoutInflater
import android.view.View import android.view.View
import android.view.ViewGroup import android.view.ViewGroup

View File

@ -16,7 +16,7 @@
package ch.dissem.apps.abit.adapter package ch.dissem.apps.abit.adapter
import android.support.v7.widget.RecyclerView import androidx.recyclerview.widget.RecyclerView
import android.view.LayoutInflater import android.view.LayoutInflater
import android.view.View import android.view.View
import android.view.ViewGroup import android.view.ViewGroup
@ -31,7 +31,7 @@ import java.util.*
*/ */
class AddressSelectorAdapter(identities: List<BitmessageAddress>) : RecyclerView.Adapter<AddressSelectorAdapter.ViewHolder>() { class AddressSelectorAdapter(identities: List<BitmessageAddress>) : RecyclerView.Adapter<AddressSelectorAdapter.ViewHolder>() {
private val data = identities.map { Selectable(it) }.toMutableList() private val data = identities.asSequence().map { Selectable(it) }.toMutableList()
override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): ViewHolder { override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): ViewHolder {
val inflater = LayoutInflater.from(parent.context) val inflater = LayoutInflater.from(parent.context)
@ -63,7 +63,7 @@ class AddressSelectorAdapter(identities: List<BitmessageAddress>) : RecyclerView
val selected: List<BitmessageAddress> val selected: List<BitmessageAddress>
get() { get() {
return data return data.asSequence()
.filter { it.selected } .filter { it.selected }
.mapTo(LinkedList()) { it.data } .mapTo(LinkedList()) { it.data }
} }

View File

@ -142,5 +142,4 @@ class ContactAdapter(
} }
} }
fun indexOf(element: BitmessageAddress) = originalData.indexOf(element)
} }

View File

@ -1,16 +1,16 @@
package ch.dissem.apps.abit.adapter package ch.dissem.apps.abit.adapter
import android.content.Context import android.content.Context
import android.support.v4.app.Fragment
import android.support.v7.widget.GridLayoutManager
import android.support.v7.widget.PopupMenu
import android.support.v7.widget.RecyclerView
import android.text.util.Linkify import android.text.util.Linkify
import android.view.LayoutInflater import android.view.LayoutInflater
import android.view.View import android.view.View
import android.view.ViewGroup import android.view.ViewGroup
import android.widget.ImageView import android.widget.ImageView
import android.widget.TextView import android.widget.TextView
import androidx.appcompat.widget.PopupMenu
import androidx.fragment.app.Fragment
import androidx.recyclerview.widget.GridLayoutManager
import androidx.recyclerview.widget.RecyclerView
import ch.dissem.apps.abit.* import ch.dissem.apps.abit.*
import ch.dissem.apps.abit.service.Singleton import ch.dissem.apps.abit.service.Singleton
import ch.dissem.apps.abit.util.Constants import ch.dissem.apps.abit.util.Constants
@ -19,18 +19,19 @@ import ch.dissem.bitmessage.entity.Conversation
import ch.dissem.bitmessage.entity.Plaintext import ch.dissem.bitmessage.entity.Plaintext
import ch.dissem.bitmessage.entity.valueobject.Label import ch.dissem.bitmessage.entity.valueobject.Label
import ch.dissem.bitmessage.ports.MessageRepository import ch.dissem.bitmessage.ports.MessageRepository
import io.reactivex.subjects.BehaviorSubject
class ConversationAdapter internal constructor( class ConversationAdapter internal constructor(
ctx: Context, ctx: Context,
private val parent: Fragment, private val parent: Fragment,
conversation: Conversation, conversation: Conversation,
private val label: Label? label: BehaviorSubject<Label>
) : RecyclerView.Adapter<ConversationAdapter.ViewHolder>() { ) : RecyclerView.Adapter<ConversationAdapter.ViewHolder>() {
private val messageRepo = Singleton.getMessageRepository(ctx) private val messageRepo = Singleton.getMessageRepository(ctx)
private var filteredMessages = conversation.messages.filter { label == null || it.labels.any { it == label } } private var filteredMessages = label.value?.let { l -> conversation.messages.filter { m -> m.labels.any { it == l } } } ?: emptyList()
override fun onCreateViewHolder( override fun onCreateViewHolder(
parent: ViewGroup, parent: ViewGroup,
@ -98,13 +99,14 @@ class ConversationAdapter internal constructor(
val sender = itemView.findViewById<TextView>(R.id.sender)!! val sender = itemView.findViewById<TextView>(R.id.sender)!!
val recipient = itemView.findViewById<TextView>(R.id.recipient)!! val recipient = itemView.findViewById<TextView>(R.id.recipient)!!
val status = itemView.findViewById<ImageView>(R.id.status)!! val status = itemView.findViewById<ImageView>(R.id.status)!!
val menu = itemView.findViewById<ImageView>(R.id.menu)!!.also { view -> val menu = itemView.findViewById<ImageView>(R.id.menu)!!.apply {
view.setOnClickListener { setOnClickListener { view ->
val popup = PopupMenu(itemView.context, view) PopupMenu(itemView.context, view).apply {
popup.menuInflater.inflate(R.menu.message, popup.menu)
popup.setOnMenuItemClickListener { menuInflater.inflate(R.menu.message, menu)
setOnMenuItemClickListener { menuItem ->
item?.let { item -> item?.let { item ->
when (it.itemId) { when (menuItem.itemId) {
R.id.reply -> { R.id.reply -> {
ComposeMessageActivity.launchReplyTo(parent, item) ComposeMessageActivity.launchReplyTo(parent, item)
true true
@ -142,7 +144,9 @@ class ConversationAdapter internal constructor(
} }
} ?: false } ?: false
} }
popup.show() show()
}
} }
} }
val text = itemView.findViewById<TextView>(R.id.text)!!.apply { val text = itemView.findViewById<TextView>(R.id.text)!!.apply {

View File

@ -2,8 +2,8 @@ package ch.dissem.apps.abit.adapter
import android.content.Context import android.content.Context
import android.content.res.ColorStateList import android.content.res.ColorStateList
import android.support.annotation.ColorInt import androidx.annotation.ColorInt
import android.support.v7.widget.RecyclerView import androidx.recyclerview.widget.RecyclerView
import android.view.LayoutInflater import android.view.LayoutInflater
import android.view.View import android.view.View
import android.view.ViewGroup import android.view.ViewGroup

View File

@ -0,0 +1,312 @@
/*
* Copyright 2015 Haruki Hasegawa
* Copyright 2016 Christian Basler
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package ch.dissem.apps.abit.adapter
import android.content.Context
import android.graphics.*
import android.view.LayoutInflater
import android.view.View
import android.view.ViewGroup
import android.widget.FrameLayout
import android.widget.ImageView
import android.widget.TextView
import androidx.core.content.ContextCompat
import androidx.recyclerview.widget.ItemTouchHelper
import androidx.recyclerview.widget.RecyclerView
import ch.dissem.apps.abit.Identicon
import ch.dissem.apps.abit.MultiIdenticon
import ch.dissem.apps.abit.R
import ch.dissem.apps.abit.util.Strings.prepareMessageExtract
import ch.dissem.apps.abit.util.getDrawable
import ch.dissem.apps.abit.util.getString
import ch.dissem.bitmessage.entity.Conversation
import ch.dissem.bitmessage.entity.Plaintext
import ch.dissem.bitmessage.entity.valueobject.Label
import java.util.*
/**
* Adapted from the basic swipeable example by Haruki Hasegawa. See
*
* @author Christian Basler
* @see [https://github.com/h6ah4i/android-advancedrecyclerview](https://github.com/h6ah4i/android-advancedrecyclerview)
*/
abstract class SwipeableAdapter<T, H>(val ctx: Context) :
RecyclerView.Adapter<H>() where H : SwipeableAdapter.AbstractViewHolder {
protected val data = LinkedList<T>()
var eventListener: EventListener? = null
protected var label: Label? = null
var selectedPosition = -1
set(value) {
val oldPosition = field
field = value
notifyItemChanged(oldPosition)
notifyItemChanged(value)
}
var activateOnItemClick: Boolean = false
protected val labelUnknown: String = ctx.getString(R.string.unknown)
open class AbstractViewHolder(v: View, adapter: SwipeableAdapter<*, *>) : RecyclerView.ViewHolder(v) {
val container = v.findViewById<FrameLayout>(R.id.container)!!
init {
itemView.setOnClickListener { adapter.eventListener?.onItemSelected(adapterPosition) }
container.setOnClickListener { adapter.eventListener?.onItemSelected(adapterPosition) }
}
}
init {
// SwipeableItemAdapter requires stable ID, and also
// have to implement the getItemId() method appropriately.
setHasStableIds(true)
}
override fun onBindViewHolder(holder: H, position: Int) {
val item = data[position]
holder.apply {
if (activateOnItemClick) {
container.setBackgroundResource(
if (position == selectedPosition)
R.drawable.bg_item_selected_state
else
R.drawable.bg_item_normal_state
)
}
setData(holder, item)
}
}
abstract fun setData(holder: H, item: T)
fun add(item: T) {
val index = data.size
data.add(item)
notifyItemInserted(index)
}
fun addFirst(item: T) {
data.addFirst(item)
notifyItemInserted(0)
}
fun addAll(items: Collection<T>) {
val index = data.size
data.addAll(items)
notifyItemRangeInserted(index, items.size)
}
fun remove(item: T) {
val itemId = getItemId(item)
val index = data.indexOfFirst { getItemId(it) == itemId }
if (index >= 0) {
removeAt(index)
}
}
fun removeAt(index: Int) {
data.removeAt(index)
notifyItemRemoved(index)
}
override fun getItemId(position: Int): Long {
return getItemId(data[position])
}
abstract fun getItemId(item: T): Long
abstract fun update(item: T)
fun clear(newLabel: Label?) {
label = newLabel
data.clear()
notifyDataSetChanged()
}
fun getItem(position: Int) = data[position]
override fun getItemCount() = data.size
}
class SwipeableConversationAdapter(ctx: Context) : SwipeableAdapter<Conversation, SwipeableConversationAdapter.ViewHolder>(ctx) {
override fun getItemId(item: Conversation) = item.id.leastSignificantBits
override fun update(item: Conversation) {
val index = data.indexOfFirst { it.id == item.id }
if (index >= 0) {
data[index] = item
notifyItemChanged(index)
}
}
override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): ViewHolder {
val inflater = LayoutInflater.from(parent.context)
val v = inflater.inflate(R.layout.conversation_row, parent, false)
return ViewHolder(v, this)
}
override fun setData(holder: ViewHolder, item: Conversation) {
holder.apply {
avatar.setImageDrawable(MultiIdenticon(item.participants))
sender.text = item.participants.sortedBy {
(it.alias?.let { 0 } ?: 1) + if (it.isChan) 2 else 0
}.map { it.alias ?: labelUnknown }.distinct().joinToString()
subject.text = prepareMessageExtract(item.subject)
extract.text = prepareMessageExtract(item.extract)
item.messages.count { it.labels.contains(label) }.let { size ->
if (size <= 1) {
count.text = ""
} else {
count.text = size.toString()
}
}
if (item.hasUnread()) {
sender.typeface = Typeface.DEFAULT_BOLD
subject.typeface = Typeface.DEFAULT_BOLD
} else {
sender.typeface = Typeface.DEFAULT
subject.typeface = Typeface.DEFAULT
}
}
}
class ViewHolder(v: View, adapter: SwipeableConversationAdapter) : AbstractViewHolder(v, adapter) {
val avatar = v.findViewById<ImageView>(R.id.avatar)!!
val status = v.findViewById<ImageView>(R.id.status)!!
val sender = v.findViewById<TextView>(R.id.sender)!!
val subject = v.findViewById<TextView>(R.id.subject)!!
val extract = v.findViewById<TextView>(R.id.text)!!
val count = v.findViewById<TextView>(R.id.count)!!
}
}
class SwipeableMessageAdapter(ctx: Context) : SwipeableAdapter<Plaintext, SwipeableMessageAdapter.ViewHolder>(ctx) {
override fun getItemId(item: Plaintext) = item.id as Long
override fun update(item: Plaintext) {
val index = data.indexOfFirst { it.id == item.id }
if (index >= 0) {
data[index] = item
notifyItemChanged(index)
}
}
override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): ViewHolder {
val inflater = LayoutInflater.from(parent.context)
val v = inflater.inflate(R.layout.message_row, parent, false)
return ViewHolder(v, this)
}
override fun setData(holder: ViewHolder, item: Plaintext) {
holder.apply {
avatar.setImageDrawable(Identicon(item.from))
status.setImageResource(item.status.getDrawable())
status.contentDescription = holder.status.context.getString(item.status.getString())
sender.text = item.from.toString()
subject.text = prepareMessageExtract(item.subject)
extract.text = prepareMessageExtract(item.text)
if (item.isUnread()) {
sender.typeface = Typeface.DEFAULT_BOLD
subject.typeface = Typeface.DEFAULT_BOLD
} else {
sender.typeface = Typeface.DEFAULT
subject.typeface = Typeface.DEFAULT
}
}
}
class ViewHolder(v: View, adapter: SwipeableMessageAdapter) : AbstractViewHolder(v, adapter) {
val avatar = v.findViewById<ImageView>(R.id.avatar)!!
val status = v.findViewById<ImageView>(R.id.status)!!
val sender = v.findViewById<TextView>(R.id.sender)!!
val subject = v.findViewById<TextView>(R.id.subject)!!
val extract = v.findViewById<TextView>(R.id.text)!!
}
}
class SwipeToDeleteCallback(ctx: Context, swipeDirs: Int, private val eventListener: EventListener) : ItemTouchHelper.SimpleCallback(0, swipeDirs) {
private val backgroundLeft = ContextCompat.getDrawable(ctx, R.drawable.bg_swipe_item_left)!!
private val backgroundRight = ContextCompat.getDrawable(ctx, R.drawable.bg_swipe_item_right)!!
private val clearPaint = Paint().apply { xfermode = PorterDuffXfermode(PorterDuff.Mode.CLEAR) }
override fun getMovementFlags(recyclerView: RecyclerView, viewHolder: RecyclerView.ViewHolder): Int {
/**
* To disable "swipe" for specific item return 0 here.
* For example:
* if (viewHolder?.itemViewType == YourAdapter.SOME_TYPE) return 0
* if (viewHolder?.adapterPosition == 0) return 0
*/
if (viewHolder.adapterPosition == 10) return 0
return super.getMovementFlags(recyclerView, viewHolder)
}
override fun onMove(recyclerView: RecyclerView, viewHolder: RecyclerView.ViewHolder, target: RecyclerView.ViewHolder) = false
override fun onChildDraw(
c: Canvas, recyclerView: RecyclerView, viewHolder: RecyclerView.ViewHolder,
dX: Float, dY: Float, actionState: Int, isCurrentlyActive: Boolean
) {
val itemView = viewHolder.itemView
val isCanceled = dX == 0f && !isCurrentlyActive
if (isCanceled) {
clearCanvas(c, itemView.right + dX, itemView.top.toFloat(), itemView.right.toFloat(), itemView.bottom.toFloat())
super.onChildDraw(c, recyclerView, viewHolder, dX, dY, actionState, isCurrentlyActive)
return
}
if (dX < 0) {
backgroundLeft.setBounds(itemView.right + dX.toInt(), itemView.top, itemView.right, itemView.bottom)
backgroundLeft.draw(c)
} else {
backgroundRight.setBounds(itemView.left, itemView.top, itemView.left + dX.toInt(), itemView.bottom)
backgroundRight.draw(c)
}
super.onChildDraw(c, recyclerView, viewHolder, dX, dY, actionState, isCurrentlyActive)
}
private fun clearCanvas(c: Canvas?, left: Float, top: Float, right: Float, bottom: Float) {
c?.drawRect(left, top, right, bottom, clearPaint)
}
override fun onSwiped(viewHolder: RecyclerView.ViewHolder, direction: Int) {
when (direction) {
ItemTouchHelper.LEFT -> eventListener.onItemDeleted(viewHolder.adapterPosition)
ItemTouchHelper.RIGHT -> eventListener.onItemArchived(viewHolder.adapterPosition)
}
}
}
interface EventListener {
fun onItemDeleted(position: Int)
fun onItemArchived(position: Int)
fun onItemSelected(position: Int)
}

View File

@ -1,275 +0,0 @@
/*
* Copyright 2015 Haruki Hasegawa
* Copyright 2016 Christian Basler
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package ch.dissem.apps.abit.adapter
import android.annotation.SuppressLint
import android.content.Context
import android.graphics.Typeface
import android.support.v7.widget.RecyclerView
import android.view.LayoutInflater
import android.view.View
import android.view.ViewGroup
import android.widget.FrameLayout
import android.widget.ImageView
import android.widget.TextView
import ch.dissem.apps.abit.MultiIdenticon
import ch.dissem.apps.abit.R
import ch.dissem.apps.abit.repository.AndroidLabelRepository.Companion.LABEL_ARCHIVE
import ch.dissem.apps.abit.util.Strings.prepareMessageExtract
import ch.dissem.bitmessage.entity.Conversation
import ch.dissem.bitmessage.entity.valueobject.Label
import com.h6ah4i.android.widget.advrecyclerview.swipeable.SwipeableItemAdapter
import com.h6ah4i.android.widget.advrecyclerview.swipeable.SwipeableItemConstants
import com.h6ah4i.android.widget.advrecyclerview.swipeable.SwipeableItemConstants.*
import com.h6ah4i.android.widget.advrecyclerview.swipeable.action.SwipeResultActionMoveToSwipedDirection
import com.h6ah4i.android.widget.advrecyclerview.swipeable.action.SwipeResultActionRemoveItem
import com.h6ah4i.android.widget.advrecyclerview.utils.AbstractSwipeableItemViewHolder
import com.h6ah4i.android.widget.advrecyclerview.utils.RecyclerViewAdapterUtils
import java.util.*
/**
* Adapted from the basic swipeable example by Haruki Hasegawa. See
*
* @author Christian Basler
* @see [https://github.com/h6ah4i/android-advancedrecyclerview](https://github.com/h6ah4i/android-advancedrecyclerview)
*/
class SwipeableConversationAdapter(ctx: Context) :
RecyclerView.Adapter<SwipeableConversationAdapter.ViewHolder>(),
SwipeableItemAdapter<SwipeableConversationAdapter.ViewHolder>, SwipeableItemConstants {
private val data = LinkedList<Conversation>()
var eventListener: EventListener? = null
private val itemViewOnClickListener: View.OnClickListener
private val swipeableViewContainerOnClickListener: View.OnClickListener
private var label: Label? = null
private var selectedPosition = -1
private var activateOnItemClick: Boolean = false
private val labelUnknown = ctx.getString(R.string.unknown)
fun setActivateOnItemClick(activateOnItemClick: Boolean) {
this.activateOnItemClick = activateOnItemClick
}
interface EventListener {
fun onItemDeleted(item: Conversation)
fun onItemArchived(item: Conversation)
fun onItemViewClicked(v: View?)
}
class ViewHolder(v: View) : AbstractSwipeableItemViewHolder(v) {
val container = v.findViewById<FrameLayout>(R.id.container)!!
val avatar = v.findViewById<ImageView>(R.id.avatar)!!
val status = v.findViewById<ImageView>(R.id.status)!!
val sender = v.findViewById<TextView>(R.id.sender)!!
val subject = v.findViewById<TextView>(R.id.subject)!!
val extract = v.findViewById<TextView>(R.id.text)!!
val count = v.findViewById<TextView>(R.id.count)!!
override fun getSwipeableContainerView() = container
}
init {
itemViewOnClickListener = View.OnClickListener { view -> onItemViewClick(view) }
swipeableViewContainerOnClickListener =
View.OnClickListener { view -> onSwipeableViewContainerClick(view) }
// SwipeableItemAdapter requires stable ID, and also
// have to implement the getItemId() method appropriately.
setHasStableIds(true)
}
fun add(item: Conversation) {
data.add(item)
notifyDataSetChanged()
}
fun addFirst(item: Conversation) {
val index = data.size
data.addFirst(item)
notifyItemInserted(index)
}
fun addAll(items: Collection<Conversation>) {
val index = data.size
data.addAll(items)
notifyItemRangeInserted(index, items.size)
}
fun remove(item: Conversation) {
val index = data.indexOf(item)
data.removeAll { it.id == item.id }
notifyItemRemoved(index)
}
fun update(item: Conversation) {
val index = data.indexOfFirst { it.id == item.id }
if (index >= 0) {
data[index] = item
notifyItemChanged(index)
}
}
fun clear(newLabel: Label?) {
label = newLabel
data.clear()
notifyDataSetChanged()
}
private fun onItemViewClick(v: View) {
eventListener?.onItemViewClicked(v)
}
private fun onSwipeableViewContainerClick(v: View) {
eventListener?.onItemViewClicked(
RecyclerViewAdapterUtils.getParentViewHolderItemView(v)
)
}
fun getItem(position: Int) = data[position]
override fun getItemId(position: Int) = data[position].id.leastSignificantBits
override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): ViewHolder {
val inflater = LayoutInflater.from(parent.context)
val v = inflater.inflate(R.layout.conversation_row, parent, false)
return ViewHolder(v)
}
override fun onBindViewHolder(holder: ViewHolder, position: Int) {
val item = data[position]
holder.apply {
if (activateOnItemClick) {
container.setBackgroundResource(
if (position == selectedPosition)
R.drawable.bg_item_selected_state
else
R.drawable.bg_item_normal_state
)
}
// set listeners
// (if the item is *pinned*, click event comes to the itemView)
itemView.setOnClickListener(itemViewOnClickListener)
// (if the item is *not pinned*, click event comes to the container)
container.setOnClickListener(swipeableViewContainerOnClickListener)
// set data
avatar.setImageDrawable(MultiIdenticon(item.participants))
sender.text = item.participants.sortedBy {
(it.alias?.let { 0 } ?: 1) + if (it.isChan) 2 else 0
}.map { it.alias ?: labelUnknown }.distinct().joinToString()
subject.text = prepareMessageExtract(item.subject)
extract.text = prepareMessageExtract(item.extract)
item.messages.count { it.labels.contains(label) }.let { size ->
if (size <= 1) {
count.text = ""
} else {
count.text = size.toString()
}
}
if (item.hasUnread()) {
sender.typeface = Typeface.DEFAULT_BOLD
subject.typeface = Typeface.DEFAULT_BOLD
} else {
sender.typeface = Typeface.DEFAULT
subject.typeface = Typeface.DEFAULT
}
}
}
override fun getItemCount() = data.size
override fun onGetSwipeReactionType(holder: ViewHolder, position: Int, x: Int, y: Int): Int =
if (label === LABEL_ARCHIVE || label?.type == Label.Type.TRASH) {
REACTION_CAN_SWIPE_LEFT or REACTION_CAN_NOT_SWIPE_RIGHT_WITH_RUBBER_BAND_EFFECT
} else {
REACTION_CAN_SWIPE_BOTH_H
}
@SuppressLint("SwitchIntDef")
override fun onSetSwipeBackground(holder: ViewHolder, position: Int, type: Int) =
holder.itemView.setBackgroundResource(
when (type) {
DRAWABLE_SWIPE_NEUTRAL_BACKGROUND -> R.drawable.bg_swipe_item_neutral
DRAWABLE_SWIPE_LEFT_BACKGROUND -> R.drawable.bg_swipe_item_left
DRAWABLE_SWIPE_RIGHT_BACKGROUND -> if (label === LABEL_ARCHIVE || label?.type == Label.Type.TRASH) {
R.drawable.bg_swipe_item_neutral
} else {
R.drawable.bg_swipe_item_right
}
else -> R.drawable.bg_swipe_item_neutral
}
)
@SuppressLint("SwitchIntDef")
override fun onSwipeItem(holder: ViewHolder, position: Int, result: Int) =
when (result) {
RESULT_SWIPED_RIGHT -> SwipeRightResultAction(this, position)
RESULT_SWIPED_LEFT -> SwipeLeftResultAction(this, position)
else -> null
}
override fun onSwipeItemStarted(holder: ViewHolder?, position: Int) = Unit
fun setSelectedPosition(selectedPosition: Int) {
val oldPosition = this.selectedPosition
this.selectedPosition = selectedPosition
notifyItemChanged(oldPosition)
notifyItemChanged(selectedPosition)
}
private class SwipeLeftResultAction internal constructor(
adapter: SwipeableConversationAdapter,
position: Int
) : SwipeResultActionMoveToSwipedDirection() {
private var adapter: SwipeableConversationAdapter? = adapter
private val item = adapter.data[position]
override fun onPerformAction() {
adapter?.eventListener?.onItemDeleted(item)
adapter?.remove(item)
}
override fun onCleanUp() {
adapter = null
}
}
private class SwipeRightResultAction internal constructor(
adapter: SwipeableConversationAdapter,
position: Int
) : SwipeResultActionRemoveItem() {
private var adapter: SwipeableConversationAdapter? = adapter
private val item = adapter.data[position]
override fun onPerformAction() {
adapter?.eventListener?.onItemArchived(item)
adapter?.remove(item)
}
override fun onCleanUp() {
adapter = null
}
}
}

View File

@ -1,262 +0,0 @@
/*
* Copyright 2015 Haruki Hasegawa
* Copyright 2016 Christian Basler
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package ch.dissem.apps.abit.adapter
import android.annotation.SuppressLint
import android.graphics.Typeface
import android.support.v7.widget.RecyclerView
import android.view.LayoutInflater
import android.view.View
import android.view.ViewGroup
import android.widget.FrameLayout
import android.widget.ImageView
import android.widget.TextView
import ch.dissem.apps.abit.Identicon
import ch.dissem.apps.abit.R
import ch.dissem.apps.abit.repository.AndroidLabelRepository.Companion.LABEL_ARCHIVE
import ch.dissem.apps.abit.util.Strings.prepareMessageExtract
import ch.dissem.apps.abit.util.getDrawable
import ch.dissem.apps.abit.util.getString
import ch.dissem.bitmessage.entity.Plaintext
import ch.dissem.bitmessage.entity.valueobject.Label
import com.h6ah4i.android.widget.advrecyclerview.swipeable.SwipeableItemAdapter
import com.h6ah4i.android.widget.advrecyclerview.swipeable.SwipeableItemConstants
import com.h6ah4i.android.widget.advrecyclerview.swipeable.SwipeableItemConstants.*
import com.h6ah4i.android.widget.advrecyclerview.swipeable.action.SwipeResultActionMoveToSwipedDirection
import com.h6ah4i.android.widget.advrecyclerview.swipeable.action.SwipeResultActionRemoveItem
import com.h6ah4i.android.widget.advrecyclerview.utils.AbstractSwipeableItemViewHolder
import com.h6ah4i.android.widget.advrecyclerview.utils.RecyclerViewAdapterUtils
import java.util.*
/**
* Adapted from the basic swipeable example by Haruki Hasegawa. See
*
* @author Christian Basler
* @see [https://github.com/h6ah4i/android-advancedrecyclerview](https://github.com/h6ah4i/android-advancedrecyclerview)
*/
class SwipeableMessageAdapter : RecyclerView.Adapter<SwipeableMessageAdapter.ViewHolder>(),
SwipeableItemAdapter<SwipeableMessageAdapter.ViewHolder>, SwipeableItemConstants {
private val data = LinkedList<Plaintext>()
var eventListener: EventListener? = null
private val itemViewOnClickListener: View.OnClickListener
private val swipeableViewContainerOnClickListener: View.OnClickListener
private var label: Label? = null
private var selectedPosition = -1
private var activateOnItemClick: Boolean = false
fun setActivateOnItemClick(activateOnItemClick: Boolean) {
this.activateOnItemClick = activateOnItemClick
}
interface EventListener {
fun onItemDeleted(item: Plaintext)
fun onItemArchived(item: Plaintext)
fun onItemViewClicked(v: View?)
}
class ViewHolder(v: View) : AbstractSwipeableItemViewHolder(v) {
val container = v.findViewById<FrameLayout>(R.id.container)!!
val avatar = v.findViewById<ImageView>(R.id.avatar)!!
val status = v.findViewById<ImageView>(R.id.status)!!
val sender = v.findViewById<TextView>(R.id.sender)!!
val subject = v.findViewById<TextView>(R.id.subject)!!
val extract = v.findViewById<TextView>(R.id.text)!!
override fun getSwipeableContainerView() = container
}
init {
itemViewOnClickListener = View.OnClickListener { view -> onItemViewClick(view) }
swipeableViewContainerOnClickListener =
View.OnClickListener { view -> onSwipeableViewContainerClick(view) }
// SwipeableItemAdapter requires stable ID, and also
// have to implement the getItemId() method appropriately.
setHasStableIds(true)
}
fun add(item: Plaintext) {
data.add(item)
notifyDataSetChanged()
}
fun addFirst(item: Plaintext) {
val index = data.size
data.addFirst(item)
notifyItemInserted(index)
}
fun addAll(items: Collection<Plaintext>) {
val index = data.size
data.addAll(items)
notifyItemRangeInserted(index, items.size)
}
fun remove(item: Plaintext) {
val index = data.indexOf(item)
data.removeAll { it.id == item.id }
notifyItemRemoved(index)
}
fun update(item: Plaintext) {
val index = data.indexOfFirst { it.id == item.id }
if (index >= 0) {
data[index] = item
notifyItemChanged(index)
}
}
fun clear(newLabel: Label?) {
label = newLabel
data.clear()
notifyDataSetChanged()
}
private fun onItemViewClick(v: View) {
eventListener?.onItemViewClicked(v)
}
private fun onSwipeableViewContainerClick(v: View) {
eventListener?.onItemViewClicked(
RecyclerViewAdapterUtils.getParentViewHolderItemView(v)
)
}
fun getItem(position: Int) = data[position]
override fun getItemId(position: Int) = data[position].id as Long
override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): ViewHolder {
val inflater = LayoutInflater.from(parent.context)
val v = inflater.inflate(R.layout.message_row, parent, false)
return ViewHolder(v)
}
override fun onBindViewHolder(holder: ViewHolder, position: Int) {
val item = data[position]
holder.apply {
if (activateOnItemClick) {
container.setBackgroundResource(
if (position == selectedPosition)
R.drawable.bg_item_selected_state
else
R.drawable.bg_item_normal_state
)
}
// set listeners
// (if the item is *pinned*, click event comes to the itemView)
itemView.setOnClickListener(itemViewOnClickListener)
// (if the item is *not pinned*, click event comes to the container)
container.setOnClickListener(swipeableViewContainerOnClickListener)
// set data
avatar.setImageDrawable(Identicon(item.from))
status.setImageResource(item.status.getDrawable())
status.contentDescription = holder.status.context.getString(item.status.getString())
sender.text = item.from.toString()
subject.text = prepareMessageExtract(item.subject)
extract.text = prepareMessageExtract(item.text)
if (item.isUnread()) {
sender.typeface = Typeface.DEFAULT_BOLD
subject.typeface = Typeface.DEFAULT_BOLD
} else {
sender.typeface = Typeface.DEFAULT
subject.typeface = Typeface.DEFAULT
}
}
}
override fun getItemCount() = data.size
override fun onGetSwipeReactionType(holder: ViewHolder, position: Int, x: Int, y: Int): Int =
if (label === LABEL_ARCHIVE || label?.type == Label.Type.TRASH) {
REACTION_CAN_SWIPE_LEFT or REACTION_CAN_NOT_SWIPE_RIGHT_WITH_RUBBER_BAND_EFFECT
} else {
REACTION_CAN_SWIPE_BOTH_H
}
@SuppressLint("SwitchIntDef")
override fun onSetSwipeBackground(holder: ViewHolder, position: Int, type: Int) =
holder.itemView.setBackgroundResource(
when (type) {
DRAWABLE_SWIPE_NEUTRAL_BACKGROUND -> R.drawable.bg_swipe_item_neutral
DRAWABLE_SWIPE_LEFT_BACKGROUND -> R.drawable.bg_swipe_item_left
DRAWABLE_SWIPE_RIGHT_BACKGROUND -> if (label === LABEL_ARCHIVE || label?.type == Label.Type.TRASH) {
R.drawable.bg_swipe_item_neutral
} else {
R.drawable.bg_swipe_item_right
}
else -> R.drawable.bg_swipe_item_neutral
}
)
@SuppressLint("SwitchIntDef")
override fun onSwipeItem(holder: ViewHolder, position: Int, result: Int) =
when (result) {
RESULT_SWIPED_RIGHT -> SwipeRightResultAction(this, position)
RESULT_SWIPED_LEFT -> SwipeLeftResultAction(this, position)
else -> null
}
override fun onSwipeItemStarted(holder: ViewHolder?, position: Int) = Unit
fun setSelectedPosition(selectedPosition: Int) {
val oldPosition = this.selectedPosition
this.selectedPosition = selectedPosition
notifyItemChanged(oldPosition)
notifyItemChanged(selectedPosition)
}
private class SwipeLeftResultAction internal constructor(
adapter: SwipeableMessageAdapter,
position: Int
) : SwipeResultActionMoveToSwipedDirection() {
private var adapter: SwipeableMessageAdapter? = adapter
private val item = adapter.data[position]
override fun onPerformAction() {
adapter?.eventListener?.onItemDeleted(item)
}
override fun onCleanUp() {
adapter = null
}
}
private class SwipeRightResultAction internal constructor(
adapter: SwipeableMessageAdapter,
position: Int
) : SwipeResultActionRemoveItem() {
private var adapter: SwipeableMessageAdapter? = adapter
private val item = adapter.data[position]
override fun onPerformAction() {
adapter?.eventListener?.onItemArchived(item)
}
override fun onCleanUp() {
adapter = null
}
}
}

View File

@ -19,12 +19,12 @@ package ch.dissem.apps.abit.dialog
import android.app.AlertDialog import android.app.AlertDialog
import android.content.Context import android.content.Context
import android.os.Bundle import android.os.Bundle
import android.support.v7.app.AppCompatDialogFragment
import android.view.LayoutInflater import android.view.LayoutInflater
import android.view.View import android.view.View
import android.view.ViewGroup import android.view.ViewGroup
import android.widget.TextView import android.widget.TextView
import android.widget.Toast import android.widget.Toast
import androidx.appcompat.app.AppCompatDialogFragment
import ch.dissem.apps.abit.ImportIdentityActivity import ch.dissem.apps.abit.ImportIdentityActivity
import ch.dissem.apps.abit.MainActivity import ch.dissem.apps.abit.MainActivity
import ch.dissem.apps.abit.R import ch.dissem.apps.abit.R
@ -33,7 +33,7 @@ import ch.dissem.bitmessage.BitmessageContext
import ch.dissem.bitmessage.entity.payload.Pubkey import ch.dissem.bitmessage.entity.payload.Pubkey
import kotlinx.android.synthetic.main.dialog_add_identity.* import kotlinx.android.synthetic.main.dialog_add_identity.*
import org.jetbrains.anko.doAsync import org.jetbrains.anko.doAsync
import org.jetbrains.anko.support.v4.startActivity import org.jetbrains.anko.startActivity
import org.jetbrains.anko.uiThread import org.jetbrains.anko.uiThread
/** /**
@ -77,7 +77,7 @@ class AddIdentityDialogFragment : AppCompatDialogFragment() {
} }
} }
} }
R.id.import_identity -> startActivity<ImportIdentityActivity>() R.id.import_identity -> ctx.startActivity<ImportIdentityActivity>()
R.id.add_chan -> addChanDialog() R.id.add_chan -> addChanDialog()
R.id.add_deterministic_address -> DeterministicIdentityDialogFragment().show(fragmentManager, "dialog") R.id.add_deterministic_address -> DeterministicIdentityDialogFragment().show(fragmentManager, "dialog")
else -> return@OnClickListener else -> return@OnClickListener

View File

@ -18,7 +18,7 @@ package ch.dissem.apps.abit.dialog
import android.content.Context import android.content.Context
import android.os.Bundle import android.os.Bundle
import android.support.v7.app.AppCompatDialogFragment import androidx.appcompat.app.AppCompatDialogFragment
import android.view.LayoutInflater import android.view.LayoutInflater
import android.view.View import android.view.View
import android.view.ViewGroup import android.view.ViewGroup

View File

@ -19,7 +19,7 @@ package ch.dissem.apps.abit.dialog
import android.app.Activity.RESULT_OK import android.app.Activity.RESULT_OK
import android.content.Intent import android.content.Intent
import android.os.Bundle import android.os.Bundle
import android.support.v7.app.AppCompatDialogFragment import androidx.appcompat.app.AppCompatDialogFragment
import android.view.LayoutInflater import android.view.LayoutInflater
import android.view.View import android.view.View
import android.view.ViewGroup import android.view.ViewGroup

View File

@ -2,7 +2,7 @@ package ch.dissem.apps.abit.drawer
import android.content.Context import android.content.Context
import android.content.Intent import android.content.Intent
import android.support.v4.app.FragmentManager import androidx.fragment.app.FragmentManager
import android.view.View import android.view.View
import android.widget.Toast import android.widget.Toast
import android.widget.Toast.LENGTH_LONG import android.widget.Toast.LENGTH_LONG

View File

@ -21,8 +21,8 @@ import android.app.NotificationChannel
import android.app.NotificationManager import android.app.NotificationManager
import android.content.Context import android.content.Context
import android.os.Build import android.os.Build
import android.support.annotation.ColorRes import androidx.annotation.ColorRes
import android.support.v4.content.ContextCompat import androidx.core.content.ContextCompat
import ch.dissem.apps.abit.R import ch.dissem.apps.abit.R
import org.jetbrains.anko.notificationManager import org.jetbrains.anko.notificationManager

View File

@ -17,7 +17,7 @@
package ch.dissem.apps.abit.notification package ch.dissem.apps.abit.notification
import android.content.Context import android.content.Context
import android.support.v4.app.NotificationCompat import androidx.core.app.NotificationCompat
import ch.dissem.apps.abit.R import ch.dissem.apps.abit.R
import ch.dissem.apps.abit.service.Job import ch.dissem.apps.abit.service.Job

View File

@ -17,8 +17,8 @@
package ch.dissem.apps.abit.notification package ch.dissem.apps.abit.notification
import android.content.Context import android.content.Context
import android.support.annotation.StringRes import androidx.annotation.StringRes
import android.support.v4.app.NotificationCompat import androidx.core.app.NotificationCompat
import ch.dissem.apps.abit.R import ch.dissem.apps.abit.R

View File

@ -21,7 +21,7 @@ import android.app.PendingIntent
import android.app.PendingIntent.FLAG_UPDATE_CURRENT import android.app.PendingIntent.FLAG_UPDATE_CURRENT
import android.content.Context import android.content.Context
import android.content.Intent import android.content.Intent
import android.support.v4.app.NotificationCompat import androidx.core.app.NotificationCompat
import ch.dissem.apps.abit.MainActivity import ch.dissem.apps.abit.MainActivity
import ch.dissem.apps.abit.R import ch.dissem.apps.abit.R
import ch.dissem.apps.abit.service.BitmessageIntentService import ch.dissem.apps.abit.service.BitmessageIntentService

View File

@ -21,9 +21,9 @@ import android.app.PendingIntent.FLAG_UPDATE_CURRENT
import android.content.Context import android.content.Context
import android.content.Intent import android.content.Intent
import android.graphics.Typeface import android.graphics.Typeface
import android.support.v4.app.NotificationCompat import androidx.core.app.NotificationCompat
import android.support.v4.app.NotificationCompat.BigTextStyle import androidx.core.app.NotificationCompat.BigTextStyle
import android.support.v4.app.NotificationCompat.InboxStyle import androidx.core.app.NotificationCompat.InboxStyle
import android.text.Spannable import android.text.Spannable
import android.text.SpannableString import android.text.SpannableString
import android.text.Spanned import android.text.Spanned

View File

@ -19,7 +19,7 @@ package ch.dissem.apps.abit.notification
import android.app.PendingIntent import android.app.PendingIntent
import android.content.Context import android.content.Context
import android.content.Intent import android.content.Intent
import android.support.v4.app.NotificationCompat import androidx.core.app.NotificationCompat
import ch.dissem.apps.abit.MainActivity import ch.dissem.apps.abit.MainActivity
import ch.dissem.apps.abit.R import ch.dissem.apps.abit.R

View File

@ -176,7 +176,7 @@ class AndroidMessageRepository(private val sql: SqlHelper, private val prefs: Pr
override fun find(where: String, offset: Int, limit: Int) = find(where, offset, limit, false) override fun find(where: String, offset: Int, limit: Int) = find(where, offset, limit, false)
fun find(where: String, offset: Int, limit: Int, separateIdentities: Boolean): List<Plaintext> { private fun find(where: String, offset: Int, limit: Int, separateIdentities: Boolean): List<Plaintext> {
val result = LinkedList<Plaintext>() val result = LinkedList<Plaintext>()
val (selectIdentityQuery, selectIdentityArgs) = getSelectIdentity(separateIdentities) val (selectIdentityQuery, selectIdentityArgs) = getSelectIdentity(separateIdentities)

View File

@ -3,9 +3,9 @@ package ch.dissem.apps.abit.service
import android.app.Service import android.app.Service
import android.content.Intent import android.content.Intent
import android.os.Binder import android.os.Binder
import android.support.annotation.DrawableRes import androidx.annotation.DrawableRes
import android.support.annotation.StringRes import androidx.annotation.StringRes
import android.support.v4.content.ContextCompat import androidx.core.content.ContextCompat
import ch.dissem.apps.abit.notification.BatchNotification import ch.dissem.apps.abit.notification.BatchNotification
import ch.dissem.apps.abit.notification.BatchNotification.Companion.ONGOING_NOTIFICATION_ID import ch.dissem.apps.abit.notification.BatchNotification.Companion.ONGOING_NOTIFICATION_ID
import org.jetbrains.anko.doAsync import org.jetbrains.anko.doAsync

View File

@ -48,6 +48,7 @@ class NodeStartupService : JobService() {
addAction(Intent.ACTION_BATTERY_CHANGED) addAction(Intent.ACTION_BATTERY_CHANGED)
} }
) )
startForeground(0, notification.notification)
NodeStartupService.running = false NodeStartupService.running = false
if (!isRunning) { if (!isRunning) {

View File

@ -19,7 +19,7 @@ package ch.dissem.apps.abit.service
import android.app.Service import android.app.Service
import android.content.Intent import android.content.Intent
import android.os.Binder import android.os.Binder
import android.support.v4.content.ContextCompat import androidx.core.content.ContextCompat
import ch.dissem.apps.abit.notification.ProofOfWorkNotification import ch.dissem.apps.abit.notification.ProofOfWorkNotification
import ch.dissem.apps.abit.notification.ProofOfWorkNotification.Companion.ONGOING_NOTIFICATION_ID import ch.dissem.apps.abit.notification.ProofOfWorkNotification.Companion.ONGOING_NOTIFICATION_ID
import ch.dissem.apps.abit.util.PowStats import ch.dissem.apps.abit.util.PowStats

View File

@ -23,19 +23,18 @@ import ch.dissem.apps.abit.R
import ch.dissem.apps.abit.adapter.SwipeableMessageAdapter import ch.dissem.apps.abit.adapter.SwipeableMessageAdapter
import ch.dissem.apps.abit.listener.MessageListener import ch.dissem.apps.abit.listener.MessageListener
import ch.dissem.apps.abit.repository.* import ch.dissem.apps.abit.repository.*
import ch.dissem.apps.abit.util.Observable
import ch.dissem.apps.abit.util.preferences import ch.dissem.apps.abit.util.preferences
import ch.dissem.bitmessage.BitmessageContext import ch.dissem.bitmessage.BitmessageContext
import ch.dissem.bitmessage.cryptography.sc.SpongyCryptography import ch.dissem.bitmessage.cryptography.sc.SpongyCryptography
import ch.dissem.bitmessage.entity.BitmessageAddress import ch.dissem.bitmessage.entity.BitmessageAddress
import ch.dissem.bitmessage.entity.payload.Pubkey import ch.dissem.bitmessage.entity.payload.Pubkey
import ch.dissem.bitmessage.entity.valueobject.Label import ch.dissem.bitmessage.entity.valueobject.Label
import ch.dissem.bitmessage.factory.BufferPool
import ch.dissem.bitmessage.networking.nio.NioNetworkHandler import ch.dissem.bitmessage.networking.nio.NioNetworkHandler
import ch.dissem.bitmessage.ports.DefaultLabeler import ch.dissem.bitmessage.ports.DefaultLabeler
import ch.dissem.bitmessage.utils.ConversationService import ch.dissem.bitmessage.utils.ConversationService
import ch.dissem.bitmessage.utils.TTL import ch.dissem.bitmessage.utils.TTL
import ch.dissem.bitmessage.utils.UnixTime.DAY import ch.dissem.bitmessage.utils.UnixTime.DAY
import io.reactivex.subjects.BehaviorSubject
import org.jetbrains.anko.doAsync import org.jetbrains.anko.doAsync
import org.jetbrains.anko.uiThread import org.jetbrains.anko.uiThread
import java.lang.ref.WeakReference import java.lang.ref.WeakReference
@ -44,7 +43,7 @@ import java.lang.ref.WeakReference
* Provides singleton objects across the application. * Provides singleton objects across the application.
*/ */
object Singleton { object Singleton {
var currentLabel = Observable<Label?>(null) var currentLabel = BehaviorSubject.create<Label>()
private var swipeableMessageAdapter: WeakReference<SwipeableMessageAdapter>? = null private var swipeableMessageAdapter: WeakReference<SwipeableMessageAdapter>? = null
val labeler = DefaultLabeler().apply { val labeler = DefaultLabeler().apply {
@ -52,7 +51,7 @@ object Singleton {
MainActivity.apply { MainActivity.apply {
runOnUiThread { runOnUiThread {
swipeableMessageAdapter?.get()?.let { swipeableMessageAdapter -> swipeableMessageAdapter?.get()?.let { swipeableMessageAdapter ->
currentLabel.value?.let { label -> currentLabel.value?.let {label ->
when { when {
label.type == Label.Type.TRASH label.type == Label.Type.TRASH
&& added.all { it.type == Label.Type.TRASH } && added.all { it.type == Label.Type.TRASH }
@ -100,7 +99,6 @@ object Singleton {
fun getBitmessageContext(context: Context): BitmessageContext = fun getBitmessageContext(context: Context): BitmessageContext =
init({ bitmessageContext }, { bitmessageContext = it }) { init({ bitmessageContext }, { bitmessageContext = it }) {
BufferPool.setLimit(4)
BitmessageContext.build { BitmessageContext.build {
TTL.pubkey = 2 * DAY TTL.pubkey = 2 * DAY
val ctx = context.applicationContext val ctx = context.applicationContext

View File

@ -1,7 +1,7 @@
package ch.dissem.apps.abit.util package ch.dissem.apps.abit.util
import android.content.Context import android.content.Context
import android.support.annotation.ColorInt import androidx.annotation.ColorInt
import ch.dissem.apps.abit.R import ch.dissem.apps.abit.R
import ch.dissem.bitmessage.entity.valueobject.Label import ch.dissem.bitmessage.entity.valueobject.Label
import com.mikepenz.community_material_typeface_library.CommunityMaterial import com.mikepenz.community_material_typeface_library.CommunityMaterial

View File

@ -1,37 +0,0 @@
package ch.dissem.apps.abit.util
import kotlin.properties.Delegates
/**
* A simple observable implementation that should be mostly
*/
class Observable<T>(value: T) {
private val observers = mutableMapOf<Any, (T) -> Unit>()
var value: T by Delegates.observable(value) { _, old, new ->
if (old != new) {
observers.values.forEach { it.invoke(new) }
}
}
/**
* The key will make sure the observer can easily be removed. Usually the key should be either
* the object that created the observer, or the observer itself, if it's easily available.
*
* Note that a map is used for observers, so if you define more than one observer with the same
* key, all previous ones will be removed. Also, the observers will be notified in no specific
* order.
*
* To prevent memory leaks, the observer must be removed if it isn't used anymore.
*/
fun addObserver(key: Any, observer: (T) -> Unit) {
observers[key] = observer
}
/**
* Remove the observer that was registered with the given key.
*/
fun removeObserver(key: Any) {
observers.remove(key)
}
}

View File

@ -57,7 +57,7 @@ class Preferences internal constructor(private val ctx: Context) {
ctx.batteryManager.isCharging ctx.batteryManager.isCharging
} else { } else {
val intent = ctx.registerReceiver(null, IntentFilter(Intent.ACTION_BATTERY_CHANGED)) val intent = ctx.registerReceiver(null, IntentFilter(Intent.ACTION_BATTERY_CHANGED))
val status = intent.getIntExtra(BatteryManager.EXTRA_STATUS, -1) val status = intent?.getIntExtra(BatteryManager.EXTRA_STATUS, -1)
status == BatteryManager.BATTERY_STATUS_CHARGING || status == BatteryManager.BATTERY_STATUS_FULL status == BatteryManager.BATTERY_STATUS_CHARGING || status == BatteryManager.BATTERY_STATUS_FULL
} }

View File

@ -0,0 +1,13 @@
<vector xmlns:android="http://schemas.android.com/apk/res/android"
android:width="24dp"
android:height="24dp"
android:viewportWidth="24.0"
android:viewportHeight="24.0">
<path
android:fillColor="#FF000000"
android:pathData="M15.67,4H14V2h-4v2H8.33C7.6,4 7,4.6 7,5.33V8h5.47L13,7v1h4V5.33C17,4.6 16.4,4 15.67,4z"
android:fillAlpha=".3"/>
<path
android:fillColor="#FF000000"
android:pathData="M13,12.5h2L11,20v-5.5H9L12.47,8H7v12.67C7,21.4 7.6,22 8.33,22h7.33c0.74,0 1.34,-0.6 1.34,-1.33V8h-4v4.5z"/>
</vector>

View File

@ -0,0 +1,8 @@
<!-- drawable/broom.xml -->
<vector xmlns:android="http://schemas.android.com/apk/res/android"
android:height="24dp"
android:width="24dp"
android:viewportWidth="24"
android:viewportHeight="24">
<path android:fillColor="#000" android:pathData="M19.36,2.72L20.78,4.14L15.06,9.85C16.13,11.39 16.28,13.24 15.38,14.44L9.06,8.12C10.26,7.22 12.11,7.37 13.65,8.44L19.36,2.72M5.93,17.57C3.92,15.56 2.69,13.16 2.35,10.92L7.23,8.83L14.67,16.27L12.58,21.15C10.34,20.81 7.94,19.58 5.93,17.57Z" />
</vector>

View File

@ -0,0 +1,9 @@
<vector xmlns:android="http://schemas.android.com/apk/res/android"
android:width="24dp"
android:height="24dp"
android:viewportWidth="24.0"
android:viewportHeight="24.0">
<path
android:fillColor="#FF000000"
android:pathData="M20,8h-2.81c-0.45,-0.78 -1.07,-1.45 -1.82,-1.96L17,4.41 15.59,3l-2.17,2.17C12.96,5.06 12.49,5 12,5c-0.49,0 -0.96,0.06 -1.41,0.17L8.41,3 7,4.41l1.62,1.63C7.88,6.55 7.26,7.22 6.81,8L4,8v2h2.09c-0.05,0.33 -0.09,0.66 -0.09,1v1L4,12v2h2v1c0,0.34 0.04,0.67 0.09,1L4,16v2h2.81c1.04,1.79 2.97,3 5.19,3s4.15,-1.21 5.19,-3L20,18v-2h-2.09c0.05,-0.33 0.09,-0.66 0.09,-1v-1h2v-2h-2v-1c0,-0.34 -0.04,-0.67 -0.09,-1L20,10L20,8zM14,16h-4v-2h4v2zM14,12h-4v-2h4v2z"/>
</vector>

View File

@ -0,0 +1,8 @@
<!-- drawable/check_all.xml -->
<vector xmlns:android="http://schemas.android.com/apk/res/android"
android:height="24dp"
android:width="24dp"
android:viewportWidth="24"
android:viewportHeight="24">
<path android:fillColor="#000" android:pathData="M0.41,13.41L6,19L7.41,17.58L1.83,12M22.24,5.58L11.66,16.17L7.5,12L6.07,13.41L11.66,19L23.66,7M18,7L16.59,5.58L10.24,11.93L11.66,13.34L18,7Z" />
</vector>

View File

@ -0,0 +1,9 @@
<vector xmlns:android="http://schemas.android.com/apk/res/android"
android:width="24dp"
android:height="24dp"
android:viewportWidth="24.0"
android:viewportHeight="24.0">
<path
android:fillColor="#FF000000"
android:pathData="M20,2L4,2c-1.1,0 -1.99,0.9 -1.99,2L2,22l4,-4h14c1.1,0 2,-0.9 2,-2L22,4c0,-1.1 -0.9,-2 -2,-2zM8,14L6,14v-2h2v2zM8,11L6,11L6,9h2v2zM8,8L6,8L6,6h2v2zM15,14h-5v-2h5v2zM18,11h-8L10,9h8v2zM18,8h-8L10,6h8v2z"/>
</vector>

View File

@ -0,0 +1,9 @@
<vector xmlns:android="http://schemas.android.com/apk/res/android"
android:width="24dp"
android:height="24dp"
android:viewportWidth="24.0"
android:viewportHeight="24.0">
<path
android:fillColor="#FF000000"
android:pathData="M9,16h6v-6h4l-7,-7 -7,7h4zM5,18h14v2L5,20z"/>
</vector>

View File

@ -0,0 +1,9 @@
<vector xmlns:android="http://schemas.android.com/apk/res/android"
android:width="24dp"
android:height="24dp"
android:viewportWidth="24.0"
android:viewportHeight="24.0">
<path
android:fillColor="#FF000000"
android:pathData="M19,9h-4V3H9v6H5l7,7 7,-7zM5,18v2h14v-2H5z"/>
</vector>

View File

@ -0,0 +1,9 @@
<vector xmlns:android="http://schemas.android.com/apk/res/android"
android:width="24dp"
android:height="24dp"
android:viewportWidth="24.0"
android:viewportHeight="24.0">
<path
android:fillColor="#FF000000"
android:pathData="M12,2C6.48,2 2,6.48 2,12s4.48,10 10,10 10,-4.48 10,-10S17.52,2 12,2zM13,17h-2v-6h2v6zM13,9h-2L11,7h2v2z"/>
</vector>

View File

@ -0,0 +1,13 @@
<vector xmlns:android="http://schemas.android.com/apk/res/android"
android:width="24dp"
android:height="24dp"
android:viewportWidth="24.0"
android:viewportHeight="24.0">
<path
android:fillColor="#FF000000"
android:pathData="M12.01,21.49L23.64,7c-0.45,-0.34 -4.93,-4 -11.64,-4C5.28,3 0.81,6.66 0.36,7l11.63,14.49 0.01,0.01 0.01,-0.01z"
android:fillAlpha=".3"/>
<path
android:fillColor="#FF000000"
android:pathData="M3.53,10.95l8.46,10.54 0.01,0.01 0.01,-0.01 8.46,-10.54C20.04,10.62 16.81,8 12,8c-4.81,0 -8.04,2.62 -8.47,2.95z"/>
</vector>

View File

@ -0,0 +1,9 @@
<vector xmlns:android="http://schemas.android.com/apk/res/android"
android:width="24dp"
android:height="24dp"
android:viewportWidth="24.0"
android:viewportHeight="24.0">
<path
android:fillColor="#FF000000"
android:pathData="M7.77,6.76L6.23,5.48 0.82,12l5.41,6.52 1.54,-1.28L3.42,12l4.35,-5.24zM7,13h2v-2L7,11v2zM17,11h-2v2h2v-2zM11,13h2v-2h-2v2zM17.77,5.48l-1.54,1.28L20.58,12l-4.35,5.24 1.54,1.28L23.18,12l-5.41,-6.52z"/>
</vector>

View File

@ -0,0 +1,9 @@
<vector xmlns:android="http://schemas.android.com/apk/res/android"
android:width="24dp"
android:height="24dp"
android:viewportWidth="24.0"
android:viewportHeight="24.0">
<path
android:fillColor="#FF000000"
android:pathData="M16,11c1.66,0 2.99,-1.34 2.99,-3S17.66,5 16,5c-1.66,0 -3,1.34 -3,3s1.34,3 3,3zM8,11c1.66,0 2.99,-1.34 2.99,-3S9.66,5 8,5C6.34,5 5,6.34 5,8s1.34,3 3,3zM8,13c-2.33,0 -7,1.17 -7,3.5L1,19h14v-2.5c0,-2.33 -4.67,-3.5 -7,-3.5zM16,13c-0.29,0 -0.62,0.02 -0.97,0.05 1.16,0.84 1.97,1.97 1.97,3.45L17,19h6v-2.5c0,-2.33 -4.67,-3.5 -7,-3.5z"/>
</vector>

View File

@ -0,0 +1,9 @@
<vector xmlns:android="http://schemas.android.com/apk/res/android"
android:width="24dp"
android:height="24dp"
android:viewportWidth="24.0"
android:viewportHeight="24.0">
<path
android:fillColor="#FF000000"
android:pathData="M9,11.24L9,7.5C9,6.12 10.12,5 11.5,5S14,6.12 14,7.5v3.74c1.21,-0.81 2,-2.18 2,-3.74C16,5.01 13.99,3 11.5,3S7,5.01 7,7.5c0,1.56 0.79,2.93 2,3.74zM18.84,15.87l-4.54,-2.26c-0.17,-0.07 -0.35,-0.11 -0.54,-0.11L13,13.5v-6c0,-0.83 -0.67,-1.5 -1.5,-1.5S10,6.67 10,7.5v10.74l-3.43,-0.72c-0.08,-0.01 -0.15,-0.03 -0.24,-0.03 -0.31,0 -0.59,0.13 -0.79,0.33l-0.79,0.8 4.94,4.94c0.27,0.27 0.65,0.44 1.06,0.44h6.79c0.75,0 1.33,-0.55 1.44,-1.28l0.75,-5.27c0.01,-0.07 0.02,-0.14 0.02,-0.2 0,-0.62 -0.38,-1.16 -0.91,-1.38z"/>
</vector>

View File

@ -1,22 +0,0 @@
<?xml version="1.0" encoding="utf-8"?>
<!--
Copyright (C) 2015 Haruki Hasegawa
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
-->
<shape
android:shape="rectangle"
xmlns:android="http://schemas.android.com/apk/res/android">
<size android:height="1px"/>
<solid android:color="@color/divider"/>
</shape>

View File

@ -1,11 +1,11 @@
<android.support.constraint.ConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android" <androidx.constraintlayout.widget.ConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto" xmlns:app="http://schemas.android.com/apk/res-auto"
xmlns:tools="http://schemas.android.com/tools" xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent" android:layout_width="match_parent"
android:layout_height="match_parent" android:layout_height="match_parent"
android:gravity="center"> android:gravity="center">
<android.support.v7.widget.Toolbar <androidx.appcompat.widget.Toolbar
android:id="@+id/toolbar" android:id="@+id/toolbar"
android:layout_width="0dp" android:layout_width="0dp"
android:layout_height="64dp" android:layout_height="64dp"
@ -19,7 +19,7 @@
tools:ignore="UnusedAttribute" tools:ignore="UnusedAttribute"
tools:layout_editor_absoluteX="0dp" /> tools:layout_editor_absoluteX="0dp" />
<android.support.constraint.Guideline <androidx.constraintlayout.widget.Guideline
android:id="@+id/guideline" android:id="@+id/guideline"
android:layout_width="wrap_content" android:layout_width="wrap_content"
android:layout_height="wrap_content" android:layout_height="wrap_content"
@ -74,4 +74,4 @@
tools:ignore="UnusedAttribute" tools:ignore="UnusedAttribute"
tools:layout_editor_absoluteX="8dp" /> tools:layout_editor_absoluteX="8dp" />
</android.support.constraint.ConstraintLayout> </androidx.constraintlayout.widget.ConstraintLayout>

View File

@ -4,7 +4,7 @@
android:layout_height="wrap_content" android:layout_height="wrap_content"
android:padding="24dp"> android:padding="24dp">
<android.support.design.widget.TextInputLayout <com.google.android.material.textfield.TextInputLayout
android:id="@+id/address_wrapper" android:id="@+id/address_wrapper"
android:layout_width="match_parent" android:layout_width="match_parent"
android:layout_height="wrap_content" android:layout_height="wrap_content"
@ -17,16 +17,17 @@
android:layout_width="match_parent" android:layout_width="match_parent"
android:layout_height="wrap_content" android:layout_height="wrap_content"
android:hint="@string/address" android:hint="@string/address"
android:importantForAutofill="no"
android:inputType="textNoSuggestions" /> android:inputType="textNoSuggestions" />
</android.support.design.widget.TextInputLayout> </com.google.android.material.textfield.TextInputLayout>
<android.support.design.widget.TextInputLayout <com.google.android.material.textfield.TextInputLayout
android:id="@+id/label_wrapper" android:id="@+id/label_wrapper"
android:layout_width="match_parent" android:layout_width="match_parent"
android:layout_height="wrap_content" android:layout_height="wrap_content"
android:layout_alignStart="@+id/address_wrapper"
android:layout_below="@+id/address_wrapper" android:layout_below="@+id/address_wrapper"
android:layout_alignStart="@+id/address_wrapper"
android:layout_marginTop="16dp"> android:layout_marginTop="16dp">
<EditText <EditText
@ -34,18 +35,19 @@
android:layout_width="match_parent" android:layout_width="match_parent"
android:layout_height="wrap_content" android:layout_height="wrap_content"
android:hint="@string/label" android:hint="@string/label"
android:importantForAutofill="no"
android:inputType="textPersonName" /> android:inputType="textPersonName" />
</android.support.design.widget.TextInputLayout> </com.google.android.material.textfield.TextInputLayout>
<Switch <Switch
android:id="@+id/subscribe" android:id="@+id/subscribe"
android:layout_width="match_parent" android:layout_width="match_parent"
android:layout_height="wrap_content" android:layout_height="wrap_content"
android:layout_alignStart="@+id/address_wrapper"
android:layout_below="@+id/label_wrapper" android:layout_below="@+id/label_wrapper"
android:layout_marginBottom="8dp" android:layout_alignStart="@+id/address_wrapper"
android:layout_marginTop="8dp" android:layout_marginTop="8dp"
android:layout_marginBottom="8dp"
android:text="@string/subscribe" /> android:text="@string/subscribe" />
<Button <Button
@ -53,10 +55,10 @@
style="?android:attr/borderlessButtonStyle" style="?android:attr/borderlessButtonStyle"
android:layout_width="wrap_content" android:layout_width="wrap_content"
android:layout_height="wrap_content" android:layout_height="wrap_content"
android:layout_alignParentEnd="true"
android:layout_below="@+id/subscribe" android:layout_below="@+id/subscribe"
android:layout_marginBottom="12dp" android:layout_alignParentEnd="true"
android:layout_marginTop="12dp" android:layout_marginTop="12dp"
android:layout_marginBottom="12dp"
android:text="@string/do_import" /> android:text="@string/do_import" />
<Button <Button

View File

@ -5,7 +5,7 @@
android:layout_height="match_parent" android:layout_height="match_parent"
android:gravity="center"> android:gravity="center">
<android.support.v7.widget.Toolbar <androidx.appcompat.widget.Toolbar
android:id="@+id/toolbar" android:id="@+id/toolbar"
android:layout_width="match_parent" android:layout_width="match_parent"
android:layout_height="?attr/actionBarSize" android:layout_height="?attr/actionBarSize"

View File

@ -14,7 +14,7 @@
android:textSize="10dp" android:textSize="10dp"
tools:ignore="SpUsage" /> tools:ignore="SpUsage" />
<android.support.design.widget.TextInputLayout <com.google.android.material.textfield.TextInputLayout
android:id="@+id/label_wrapper" android:id="@+id/label_wrapper"
android:layout_width="match_parent" android:layout_width="match_parent"
android:layout_height="wrap_content" android:layout_height="wrap_content"
@ -27,9 +27,10 @@
android:layout_width="match_parent" android:layout_width="match_parent"
android:layout_height="wrap_content" android:layout_height="wrap_content"
android:hint="@string/label" android:hint="@string/label"
android:importantForAutofill="no"
android:inputType="textPersonName" /> android:inputType="textPersonName" />
</android.support.design.widget.TextInputLayout> </com.google.android.material.textfield.TextInputLayout>
<Switch <Switch
android:id="@+id/subscribe" android:id="@+id/subscribe"

View File

@ -1,5 +1,5 @@
<?xml version="1.0" encoding="utf-8"?> <?xml version="1.0" encoding="utf-8"?>
<android.support.design.widget.CoordinatorLayout <androidx.coordinatorlayout.widget.CoordinatorLayout
xmlns:android="http://schemas.android.com/apk/res/android" xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto" xmlns:app="http://schemas.android.com/apk/res-auto"
xmlns:tools="http://schemas.android.com/tools" xmlns:tools="http://schemas.android.com/tools"
@ -19,11 +19,11 @@
app:layout_behavior="@string/appbar_scrolling_view_behavior"> app:layout_behavior="@string/appbar_scrolling_view_behavior">
</TextView> </TextView>
<android.support.design.widget.AppBarLayout <com.google.android.material.appbar.AppBarLayout
android:layout_width="match_parent" android:layout_width="match_parent"
android:layout_height="wrap_content"> android:layout_height="wrap_content">
<android.support.v7.widget.Toolbar <androidx.appcompat.widget.Toolbar
android:id="@+id/toolbar" android:id="@+id/toolbar"
android:layout_width="match_parent" android:layout_width="match_parent"
android:layout_height="?attr/actionBarSize" android:layout_height="?attr/actionBarSize"
@ -36,6 +36,6 @@
app:popupTheme="@style/ThemeOverlay.AppCompat.Light" app:popupTheme="@style/ThemeOverlay.AppCompat.Light"
tools:ignore="UnusedAttribute"/> tools:ignore="UnusedAttribute"/>
</android.support.design.widget.AppBarLayout> </com.google.android.material.appbar.AppBarLayout>
</android.support.design.widget.CoordinatorLayout> </androidx.coordinatorlayout.widget.CoordinatorLayout>

View File

@ -14,15 +14,15 @@
~ limitations under the License. ~ limitations under the License.
--> -->
<android.support.constraint.ConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android" <androidx.constraintlayout.widget.ConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto" xmlns:app="http://schemas.android.com/apk/res-auto"
xmlns:tools="http://schemas.android.com/tools" xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent" android:layout_width="match_parent"
android:layout_height="match_parent" android:layout_height="match_parent"
android:paddingBottom="18dp"
android:paddingEnd="24dp"
android:paddingStart="24dp" android:paddingStart="24dp"
android:paddingTop="18dp"> android:paddingTop="18dp"
android:paddingEnd="24dp"
android:paddingBottom="18dp">
<TextView <TextView
android:id="@+id/description" android:id="@+id/description"
@ -34,7 +34,7 @@
tools:layout_constraintLeft_creator="1" tools:layout_constraintLeft_creator="1"
tools:layout_constraintTop_creator="1" /> tools:layout_constraintTop_creator="1" />
<android.support.design.widget.TextInputLayout <com.google.android.material.textfield.TextInputLayout
android:id="@+id/label_wrapper" android:id="@+id/label_wrapper"
android:layout_width="match_parent" android:layout_width="match_parent"
android:layout_height="wrap_content" android:layout_height="wrap_content"
@ -47,11 +47,12 @@
android:layout_width="match_parent" android:layout_width="match_parent"
android:layout_height="wrap_content" android:layout_height="wrap_content"
android:hint="@string/label" android:hint="@string/label"
android:autofillHints="label"
android:inputType="text" /> android:inputType="text" />
</android.support.design.widget.TextInputLayout> </com.google.android.material.textfield.TextInputLayout>
<android.support.design.widget.TextInputLayout <com.google.android.material.textfield.TextInputLayout
android:id="@+id/passphrase_wrapper" android:id="@+id/passphrase_wrapper"
android:layout_width="match_parent" android:layout_width="match_parent"
android:layout_height="wrap_content" android:layout_height="wrap_content"
@ -63,11 +64,12 @@
android:layout_width="match_parent" android:layout_width="match_parent"
android:layout_height="wrap_content" android:layout_height="wrap_content"
android:hint="@string/passphrase" android:hint="@string/passphrase"
android:autofillHints="passphrase"
android:inputType="textMultiLine" /> android:inputType="textMultiLine" />
</android.support.design.widget.TextInputLayout> </com.google.android.material.textfield.TextInputLayout>
<android.support.design.widget.TextInputLayout <com.google.android.material.textfield.TextInputLayout
android:id="@+id/number_of_identities_wrapper" android:id="@+id/number_of_identities_wrapper"
android:layout_width="match_parent" android:layout_width="match_parent"
android:layout_height="wrap_content" android:layout_height="wrap_content"
@ -80,11 +82,12 @@
android:layout_height="wrap_content" android:layout_height="wrap_content"
android:ems="10" android:ems="10"
android:hint="@string/number_of_identities" android:hint="@string/number_of_identities"
android:autofillHints="numberOfIdentities"
android:inputType="number" android:inputType="number"
android:text="1" android:text="1"
tools:ignore="HardcodedText" /> tools:ignore="HardcodedText" />
</android.support.design.widget.TextInputLayout> </com.google.android.material.textfield.TextInputLayout>
<Switch <Switch
android:id="@+id/shorter" android:id="@+id/shorter"
@ -115,4 +118,4 @@
app:layout_constraintBottom_toBottomOf="@id/ok" app:layout_constraintBottom_toBottomOf="@id/ok"
app:layout_constraintRight_toLeftOf="@id/ok" /> app:layout_constraintRight_toLeftOf="@id/ok" />
</android.support.constraint.ConstraintLayout> </androidx.constraintlayout.widget.ConstraintLayout>

View File

@ -15,7 +15,7 @@
~ limitations under the License. ~ limitations under the License.
--> -->
<android.support.constraint.ConstraintLayout <androidx.constraintlayout.widget.ConstraintLayout
xmlns:android="http://schemas.android.com/apk/res/android" xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto" xmlns:app="http://schemas.android.com/apk/res-auto"
xmlns:tools="http://schemas.android.com/tools" xmlns:tools="http://schemas.android.com/tools"
@ -98,4 +98,4 @@
android:textColor="@color/colorAccent" android:textColor="@color/colorAccent"
app:layout_constraintRight_toLeftOf="@+id/ok" app:layout_constraintRight_toLeftOf="@+id/ok"
app:layout_constraintTop_toBottomOf="@+id/radioGroup"/> app:layout_constraintTop_toBottomOf="@+id/radioGroup"/>
</android.support.constraint.ConstraintLayout> </androidx.constraintlayout.widget.ConstraintLayout>

View File

@ -15,7 +15,7 @@
~ limitations under the License. ~ limitations under the License.
--> -->
<android.support.constraint.ConstraintLayout <androidx.constraintlayout.widget.ConstraintLayout
xmlns:android="http://schemas.android.com/apk/res/android" xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto" xmlns:app="http://schemas.android.com/apk/res-auto"
xmlns:tools="http://schemas.android.com/tools" xmlns:tools="http://schemas.android.com/tools"
@ -56,4 +56,4 @@
app:layout_constraintEnd_toEndOf="@id/description" app:layout_constraintEnd_toEndOf="@id/description"
app:layout_constraintTop_toBottomOf="@+id/ok" app:layout_constraintTop_toBottomOf="@+id/ok"
tools:layout_editor_absoluteX="8dp"/> tools:layout_editor_absoluteX="8dp"/>
</android.support.constraint.ConstraintLayout> </androidx.constraintlayout.widget.ConstraintLayout>

View File

@ -14,5 +14,6 @@
android:layout_height="wrap_content" android:layout_height="wrap_content"
android:layout_gravity="center_horizontal" android:layout_gravity="center_horizontal"
android:hint="@string/passphrase" android:hint="@string/passphrase"
android:autofillHints="passphrase"
android:inputType="textMultiLine"/> android:inputType="textMultiLine"/>
</LinearLayout> </LinearLayout>

View File

@ -1,5 +1,4 @@
<?xml version="1.0" encoding="utf-8"?> <?xml version="1.0" encoding="utf-8"?><!--
<!--
~ Copyright 2015 Christian Basler ~ Copyright 2015 Christian Basler
~ ~
~ Licensed under the Apache License, Version 2.0 (the "License"); ~ Licensed under the Apache License, Version 2.0 (the "License");
@ -28,19 +27,20 @@
android:layout_alignParentTop="true" android:layout_alignParentTop="true"
android:layout_margin="16dp" android:layout_margin="16dp"
android:src="@color/colorAccent" android:src="@color/colorAccent"
tools:ignore="ContentDescription"/> tools:ignore="ContentDescription" />
<EditText <EditText
android:id="@+id/name" android:id="@+id/name"
android:layout_width="0dp" android:layout_width="0dp"
android:layout_height="wrap_content" android:layout_height="wrap_content"
android:layout_alignParentEnd="true"
android:layout_alignTop="@+id/avatar" android:layout_alignTop="@+id/avatar"
android:layout_alignParentEnd="true"
android:layout_marginEnd="16dp" android:layout_marginEnd="16dp"
android:layout_toEndOf="@+id/avatar" android:layout_toEndOf="@+id/avatar"
android:importantForAutofill="no"
android:inputType="textPersonName" android:inputType="textPersonName"
android:text="" android:text=""
tools:ignore="LabelFor"/> tools:ignore="LabelFor" />
<TextView <TextView
android:id="@+id/address" android:id="@+id/address"
@ -52,7 +52,7 @@
android:paddingRight="16dp" android:paddingRight="16dp"
android:textAppearance="?android:attr/textAppearanceSmall" android:textAppearance="?android:attr/textAppearanceSmall"
android:textStyle="bold" android:textStyle="bold"
tools:text="BM-XyYxXyYxXyYxXyYxXyYx"/> tools:text="BM-XyYxXyYxXyYxXyYxXyYx" />
<TextView <TextView
android:id="@+id/stream_number" android:id="@+id/stream_number"
@ -64,7 +64,7 @@
android:paddingLeft="16dp" android:paddingLeft="16dp"
android:paddingRight="16dp" android:paddingRight="16dp"
android:textAppearance="?android:attr/textAppearanceSmall" android:textAppearance="?android:attr/textAppearanceSmall"
tools:text="Stream #"/> tools:text="Stream #" />
<Switch <Switch
android:id="@+id/active" android:id="@+id/active"
@ -72,21 +72,21 @@
android:layout_height="wrap_content" android:layout_height="wrap_content"
android:layout_below="@+id/stream_number" android:layout_below="@+id/stream_number"
android:paddingLeft="16dp" android:paddingLeft="16dp"
android:paddingRight="16dp"
android:paddingTop="16dp" android:paddingTop="16dp"
android:text="@string/subscribed"/> android:paddingRight="16dp"
android:text="@string/subscribed" />
<ImageView <ImageView
android:id="@+id/pubkey_available" android:id="@+id/pubkey_available"
android:layout_width="wrap_content" android:layout_width="wrap_content"
android:layout_height="wrap_content" android:layout_height="wrap_content"
android:layout_alignParentStart="true"
android:layout_below="@+id/active" android:layout_below="@+id/active"
android:paddingEnd="4dp" android:layout_alignParentStart="true"
android:paddingStart="16dp" android:paddingStart="16dp"
android:paddingTop="16dp" android:paddingTop="16dp"
android:paddingEnd="4dp"
android:src="@drawable/public_key" android:src="@drawable/public_key"
tools:ignore="ContentDescription"/> tools:ignore="ContentDescription" />
<TextView <TextView
android:id="@+id/pubkey_available_desc" android:id="@+id/pubkey_available_desc"
@ -95,25 +95,25 @@
android:layout_alignBottom="@id/pubkey_available" android:layout_alignBottom="@id/pubkey_available"
android:layout_alignParentEnd="true" android:layout_alignParentEnd="true"
android:layout_toEndOf="@id/pubkey_available" android:layout_toEndOf="@id/pubkey_available"
android:paddingEnd="16dp"
android:paddingStart="0dp" android:paddingStart="0dp"
android:paddingEnd="16dp"
android:text="@string/pubkey_available" android:text="@string/pubkey_available"
android:textAppearance="?android:attr/textAppearanceSmall"/> android:textAppearance="?android:attr/textAppearanceSmall" />
<ImageView <ImageView
android:id="@+id/qr_code" android:id="@+id/qr_code"
android:layout_width="0dp" android:layout_width="0dp"
android:layout_height="0dp" android:layout_height="0dp"
android:layout_alignParentBottom="true"
android:layout_alignParentEnd="true"
android:layout_alignParentStart="true"
android:layout_below="@+id/pubkey_available" android:layout_below="@+id/pubkey_available"
android:layout_marginBottom="64dp" android:layout_alignParentStart="true"
android:layout_marginEnd="16dp" android:layout_alignParentEnd="true"
android:layout_alignParentBottom="true"
android:layout_marginStart="16dp" android:layout_marginStart="16dp"
android:layout_marginTop="24dp" android:layout_marginTop="24dp"
android:layout_marginEnd="16dp"
android:layout_marginBottom="64dp"
android:contentDescription="@string/alt_qr_code" android:contentDescription="@string/alt_qr_code"
android:elevation="2dp" android:elevation="2dp"
tools:ignore="UnusedAttribute" tools:ignore="UnusedAttribute"
tools:src="@drawable/public_key"/> tools:src="@drawable/public_key" />
</RelativeLayout> </RelativeLayout>

View File

@ -4,7 +4,7 @@
android:layout_height="match_parent"> android:layout_height="match_parent">
<ListView <ListView
android:id="@id/android:list" android:id="@android:id/list"
android:layout_width="wrap_content" android:layout_width="wrap_content"
android:layout_height="wrap_content" android:layout_height="wrap_content"
android:layout_alignParentBottom="true" android:layout_alignParentBottom="true"

View File

@ -24,7 +24,7 @@
android:layout_width="match_parent" android:layout_width="match_parent"
android:layout_height="wrap_content" /> android:layout_height="wrap_content" />
<android.support.design.widget.TextInputLayout <com.google.android.material.textfield.TextInputLayout
android:layout_width="match_parent" android:layout_width="match_parent"
android:layout_height="wrap_content" android:layout_height="wrap_content"
android:paddingTop="4dp"> android:paddingTop="4dp">
@ -33,13 +33,14 @@
android:id="@+id/recipient_input" android:id="@+id/recipient_input"
android:layout_width="match_parent" android:layout_width="match_parent"
android:layout_height="wrap_content" android:layout_height="wrap_content"
android:autofillHints="bitmessageAddress"
android:hint="@string/to" android:hint="@string/to"
android:inputType="textNoSuggestions" android:inputType="textNoSuggestions"
android:maxLines="1" /> android:maxLines="1" />
</android.support.design.widget.TextInputLayout> </com.google.android.material.textfield.TextInputLayout>
<android.support.design.widget.TextInputLayout <com.google.android.material.textfield.TextInputLayout
android:layout_width="match_parent" android:layout_width="match_parent"
android:layout_height="wrap_content"> android:layout_height="wrap_content">
@ -47,17 +48,19 @@
android:id="@+id/subject_input" android:id="@+id/subject_input"
android:layout_width="match_parent" android:layout_width="match_parent"
android:layout_height="wrap_content" android:layout_height="wrap_content"
android:autofillHints="subject"
android:hint="@string/subject" android:hint="@string/subject"
android:inputType="textEmailSubject" android:inputType="textEmailSubject"
android:textAppearance="?android:attr/textAppearanceLarge" /> android:textAppearance="?android:attr/textAppearanceLarge" />
</android.support.design.widget.TextInputLayout> </com.google.android.material.textfield.TextInputLayout>
<EditText <EditText
android:id="@+id/body_input" android:id="@+id/body_input"
android:layout_width="match_parent" android:layout_width="match_parent"
android:layout_height="wrap_content" android:layout_height="wrap_content"
android:layout_weight="1" android:layout_weight="1"
android:autofillHints="body, message"
android:gravity="start|top" android:gravity="start|top"
android:hint="@string/compose_body_hint" android:hint="@string/compose_body_hint"
android:inputType="textMultiLine|textCapSentences" android:inputType="textMultiLine|textCapSentences"

View File

@ -41,7 +41,7 @@
android:layout_below="@id/subject" android:layout_below="@id/subject"
android:background="@color/divider" /> android:background="@color/divider" />
<android.support.v7.widget.RecyclerView <androidx.recyclerview.widget.RecyclerView
android:id="@+id/messages" android:id="@+id/messages"
android:layout_width="fill_parent" android:layout_width="fill_parent"
android:layout_height="wrap_content" android:layout_height="wrap_content"

View File

@ -15,7 +15,7 @@
~ limitations under the License. ~ limitations under the License.
--> -->
<android.support.constraint.ConstraintLayout <androidx.constraintlayout.widget.ConstraintLayout
xmlns:android="http://schemas.android.com/apk/res/android" xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto" xmlns:app="http://schemas.android.com/apk/res-auto"
android:layout_width="match_parent" android:layout_width="match_parent"
@ -41,6 +41,7 @@
android:gravity="start|top" android:gravity="start|top"
android:hint="@string/wif_string" android:hint="@string/wif_string"
android:inputType="textMultiLine|text" android:inputType="textMultiLine|text"
android:autofillHints="wif, comment, data"
app:layout_constraintBottom_toTopOf="@+id/next" app:layout_constraintBottom_toTopOf="@+id/next"
app:layout_constraintEnd_toEndOf="parent" app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent" app:layout_constraintStart_toStartOf="parent"
@ -57,4 +58,4 @@
app:layout_constraintBottom_toBottomOf="parent" app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintRight_toRightOf="parent"/> app:layout_constraintRight_toRightOf="parent"/>
</android.support.constraint.ConstraintLayout> </androidx.constraintlayout.widget.ConstraintLayout>

View File

@ -15,7 +15,7 @@
~ limitations under the License. ~ limitations under the License.
--> -->
<android.support.constraint.ConstraintLayout <androidx.constraintlayout.widget.ConstraintLayout
xmlns:android="http://schemas.android.com/apk/res/android" xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto" xmlns:app="http://schemas.android.com/apk/res-auto"
android:layout_width="match_parent" android:layout_width="match_parent"
@ -33,7 +33,7 @@
app:layout_constraintLeft_toLeftOf="parent" app:layout_constraintLeft_toLeftOf="parent"
app:layout_constraintTop_toTopOf="parent"/> app:layout_constraintTop_toTopOf="parent"/>
<android.support.v7.widget.RecyclerView <androidx.recyclerview.widget.RecyclerView
android:id="@+id/recycler_view" android:id="@+id/recycler_view"
android:layout_width="match_parent" android:layout_width="match_parent"
android:layout_height="0dp" android:layout_height="0dp"
@ -55,4 +55,4 @@
app:layout_constraintBottom_toBottomOf="parent" app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintRight_toRightOf="parent"/> app:layout_constraintRight_toRightOf="parent"/>
</android.support.constraint.ConstraintLayout> </androidx.constraintlayout.widget.ConstraintLayout>

View File

@ -78,7 +78,7 @@
android:paddingRight="8dp" android:paddingRight="8dp"
tools:text="Recipient" /> tools:text="Recipient" />
<android.support.v7.widget.RecyclerView <androidx.recyclerview.widget.RecyclerView
android:id="@+id/parents" android:id="@+id/parents"
android:layout_width="fill_parent" android:layout_width="fill_parent"
android:layout_height="wrap_content" android:layout_height="wrap_content"
@ -99,7 +99,7 @@
tools:text="Message Body" tools:text="Message Body"
android:textIsSelectable="true" /> android:textIsSelectable="true" />
<android.support.v7.widget.RecyclerView <androidx.recyclerview.widget.RecyclerView
android:id="@+id/labels" android:id="@+id/labels"
android:layout_width="fill_parent" android:layout_width="fill_parent"
android:layout_height="wrap_content" android:layout_height="wrap_content"
@ -108,7 +108,7 @@
android:layout_marginRight="16dp" android:layout_marginRight="16dp"
android:layout_marginBottom="16dp"/> android:layout_marginBottom="16dp"/>
<android.support.v7.widget.RecyclerView <androidx.recyclerview.widget.RecyclerView
android:id="@+id/responses" android:id="@+id/responses"
android:layout_width="fill_parent" android:layout_width="fill_parent"
android:layout_height="wrap_content" android:layout_height="wrap_content"

View File

@ -4,7 +4,7 @@
android:layout_width="match_parent" android:layout_width="match_parent"
android:layout_height="match_parent"> android:layout_height="match_parent">
<android.support.v7.widget.RecyclerView <androidx.recyclerview.widget.RecyclerView
android:id="@+id/recycler_view" android:id="@+id/recycler_view"
android:layout_width="match_parent" android:layout_width="match_parent"
android:layout_height="0dp" android:layout_height="0dp"

View File

@ -88,7 +88,7 @@
android:textIsSelectable="true" android:textIsSelectable="true"
tools:text="Message Body" /> tools:text="Message Body" />
<android.support.v7.widget.RecyclerView <androidx.recyclerview.widget.RecyclerView
android:id="@+id/labels" android:id="@+id/labels"
android:layout_width="fill_parent" android:layout_width="fill_parent"
android:layout_height="wrap_content" android:layout_height="wrap_content"

View File

@ -1,5 +1,5 @@
<?xml version="1.0" encoding="utf-8"?> <?xml version="1.0" encoding="utf-8"?>
<android.support.design.widget.CoordinatorLayout xmlns:android="http://schemas.android.com/apk/res/android" <androidx.coordinatorlayout.widget.CoordinatorLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto" xmlns:app="http://schemas.android.com/apk/res-auto"
xmlns:tools="http://schemas.android.com/tools" xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent" android:layout_width="match_parent"
@ -16,11 +16,11 @@
tools:context=".ComposeMessageActivity" tools:context=".ComposeMessageActivity"
tools:layout="@layout/fragment_compose_message"/> tools:layout="@layout/fragment_compose_message"/>
<android.support.design.widget.AppBarLayout <com.google.android.material.appbar.AppBarLayout
android:layout_width="match_parent" android:layout_width="match_parent"
android:layout_height="wrap_content"> android:layout_height="wrap_content">
<android.support.v7.widget.Toolbar <androidx.appcompat.widget.Toolbar
android:id="@+id/toolbar" android:id="@+id/toolbar"
android:layout_width="match_parent" android:layout_width="match_parent"
android:layout_height="?attr/actionBarSize" android:layout_height="?attr/actionBarSize"
@ -30,7 +30,7 @@
app:popupTheme="@style/ThemeOverlay.AppCompat.Light" app:popupTheme="@style/ThemeOverlay.AppCompat.Light"
tools:ignore="UnusedAttribute"/> tools:ignore="UnusedAttribute"/>
</android.support.design.widget.AppBarLayout> </com.google.android.material.appbar.AppBarLayout>
</android.support.design.widget.CoordinatorLayout> </androidx.coordinatorlayout.widget.CoordinatorLayout>

View File

@ -1,5 +1,5 @@
<?xml version="1.0" encoding="utf-8"?> <?xml version="1.0" encoding="utf-8"?>
<android.support.design.widget.CoordinatorLayout xmlns:android="http://schemas.android.com/apk/res/android" <androidx.coordinatorlayout.widget.CoordinatorLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto" xmlns:app="http://schemas.android.com/apk/res-auto"
xmlns:tools="http://schemas.android.com/tools" xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent" android:layout_width="match_parent"
@ -16,11 +16,11 @@
tools:context=".ComposeMessageActivity" tools:context=".ComposeMessageActivity"
tools:layout="@layout/fragment_compose_message"/> tools:layout="@layout/fragment_compose_message"/>
<android.support.design.widget.AppBarLayout <com.google.android.material.appbar.AppBarLayout
android:layout_width="match_parent" android:layout_width="match_parent"
android:layout_height="wrap_content"> android:layout_height="wrap_content">
<android.support.v7.widget.Toolbar <androidx.appcompat.widget.Toolbar
android:id="@+id/toolbar" android:id="@+id/toolbar"
android:layout_width="match_parent" android:layout_width="match_parent"
android:layout_height="?attr/actionBarSize" android:layout_height="?attr/actionBarSize"
@ -31,7 +31,7 @@
app:popupTheme="@style/ThemeOverlay.AppCompat.Light" app:popupTheme="@style/ThemeOverlay.AppCompat.Light"
tools:ignore="UnusedAttribute"/> tools:ignore="UnusedAttribute"/>
</android.support.design.widget.AppBarLayout> </com.google.android.material.appbar.AppBarLayout>
</android.support.design.widget.CoordinatorLayout> </androidx.coordinatorlayout.widget.CoordinatorLayout>

View File

@ -141,9 +141,8 @@ Als Alternative kann in den Einstellungen ein vertrauenswürdiger Knoten konfigu
<string name="emulate_conversations_initialize">Bestehende Nachrichten nach Betreff gruppieren</string> <string name="emulate_conversations_initialize">Bestehende Nachrichten nach Betreff gruppieren</string>
<string name="preference_group_advanced">Erweitert</string> <string name="preference_group_advanced">Erweitert</string>
<string name="preference_group_network_and_performance">Netzwerk &amp; Performanz</string> <string name="preference_group_network_and_performance">Netzwerk &amp; Performanz</string>
<string name="preference_group_network_and_performance_summary">Feineinstellungen für Netzwerk und Protokoll-Details</string>
<string name="preference_group_user_experience">Verhalten</string> <string name="preference_group_user_experience">Verhalten</string>
<string name="preference_group_user_experience_summary">Ändern, wie Nachrichten dargestellt werden</string> <string name="preference_group_app">App</string>
<string name="bitmessage_service_description">Hält die Verbindung zum Bitmessage-Netzwerk.</string> <string name="bitmessage_service_description">Hält die Verbindung zum Bitmessage-Netzwerk.</string>
<string name="preference_port">Port</string> <string name="preference_port">Port</string>
</resources> </resources>

View File

@ -37,10 +37,6 @@
<string name="archive">Archive</string> <string name="archive">Archive</string>
<string name="empty_trash">Empty Trash</string> <string name="empty_trash">Empty Trash</string>
<string name="stream_number">Stream #%d</string> <string name="stream_number">Stream #%d</string>
<string name="trusted_node">Trusted node</string>
<string name="trusted_node_summary">Use this node for synchronization</string>
<string name="sync_timeout">Synchronization Timeout</string>
<string name="sync_timeout_summary">Timeout in seconds</string>
<string name="write_message">Write message</string> <string name="write_message">Write message</string>
<string name="full_node">Full node</string> <string name="full_node">Full node</string>
<string name="send">Send</string> <string name="send">Send</string>
@ -49,12 +45,9 @@
<string name="proof_of_work_title">Proof of Work</string> <string name="proof_of_work_title">Proof of Work</string>
<string name="proof_of_work_text_0">Doing work to send message</string> <string name="proof_of_work_text_0">Doing work to send message</string>
<string name="proof_of_work_text_n" tools:ignore="PluralsCandidate">Doing work to send message (%1$d queued)</string> <string name="proof_of_work_text_n" tools:ignore="PluralsCandidate">Doing work to send message (%1$d queued)</string>
<string name="error_invalid_sync_port">Invalid port in synchronization settings: %s</string>
<string name="compose_body_hint">Write message</string> <string name="compose_body_hint">Write message</string>
<string name="contacts_and_subscriptions">Contacts</string> <string name="contacts_and_subscriptions">Contacts</string>
<string name="subscribed">Subscribed</string> <string name="subscribed">Subscribed</string>
<string name="server_pow">Server POW</string>
<string name="server_pow_summary">Trusted node does proof of work</string>
<string name="full_node_warning">Running a full Bitmessage node uses a lot of traffic, which could be expensive on a mobile network. Are you sure you want to start a full node?</string> <string name="full_node_warning">Running a full Bitmessage node uses a lot of traffic, which could be expensive on a mobile network. Are you sure you want to start a full node?</string>
<string name="about">About Abit</string> <string name="about">About Abit</string>
<string name="about_summary">Open source dependencies.</string> <string name="about_summary">Open source dependencies.</string>
@ -142,13 +135,10 @@ As an alternative you could configure a trusted node in the settings, but as of
<string name="emulate_conversations_initialize">Group existing messages by subject</string> <string name="emulate_conversations_initialize">Group existing messages by subject</string>
<string name="emulate_conversations_batch">Grouping existing messages by subject</string> <string name="emulate_conversations_batch">Grouping existing messages by subject</string>
<string name="preference_group_user_experience">Behaviour</string> <string name="preference_group_user_experience">Behaviour</string>
<string name="preference_group_user_experience_summary">Change how messages are displayed</string>
<string name="preference_group_network_and_performance">Network &amp; Performance</string> <string name="preference_group_network_and_performance">Network &amp; Performance</string>
<string name="preference_group_network_and_performance_summary">Tweak network usage and protocol details</string>
<string name="preference_group_advanced">Advanced</string> <string name="preference_group_advanced">Advanced</string>
<string name="preference_group_advanced_summary"></string>
<string name="preference_group_experimental">Experimental</string> <string name="preference_group_experimental">Experimental</string>
<string name="preference_group_experimental_summary">Only change if you know what you\'re doing</string> <string name="preference_group_app">App</string>
<string name="require_charging">Require charging</string> <string name="require_charging">Require charging</string>
<string name="require_charging_summary">Only connect when device is plugged in</string> <string name="require_charging_summary">Only connect when device is plugged in</string>
<string name="unknown">Unknown</string> <string name="unknown">Unknown</string>

View File

@ -1,92 +1,94 @@
<?xml version="1.0" encoding="utf-8"?> <?xml version="1.0" encoding="utf-8"?>
<PreferenceScreen xmlns:android="http://schemas.android.com/apk/res/android"> <PreferenceScreen xmlns:android="http://schemas.android.com/apk/res/android">
<PreferenceScreen <PreferenceCategory android:title="@string/preference_group_user_experience">
android:key="preference_ux"
android:persistent="false"
android:summary="@string/preference_group_user_experience_summary"
android:title="@string/preference_group_user_experience">
<SwitchPreferenceCompat <SwitchPreferenceCompat
android:defaultValue="false" android:defaultValue="false"
android:icon="@drawable/ic_separate_identities"
android:key="separate_identities" android:key="separate_identities"
android:summary="@string/preference_separate_identities_summary" android:summary="@string/preference_separate_identities_summary"
android:title="@string/preference_separate_identities" /> android:title="@string/preference_separate_identities" />
<SwitchPreferenceCompat <SwitchPreferenceCompat
android:defaultValue="true" android:defaultValue="true"
android:icon="@drawable/ic_emulate_conversations"
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" />
<Preference <Preference
android:defaultValue="true" android:defaultValue="true"
android:icon="@drawable/ic_emulate_conversations"
android:key="emulate_conversations_initialize" android:key="emulate_conversations_initialize"
android:summary="@string/emulate_conversations_summary" android:summary="@string/emulate_conversations_summary"
android:title="@string/emulate_conversations_initialize" /> android:title="@string/emulate_conversations_initialize" />
</PreferenceScreen> </PreferenceCategory>
<PreferenceScreen <PreferenceCategory android:title="@string/preference_group_network_and_performance">
android:key="preference_network_and_performance"
android:persistent="false"
android:summary="@string/preference_group_network_and_performance_summary"
android:title="@string/preference_group_network_and_performance">
<SwitchPreferenceCompat <SwitchPreferenceCompat
android:defaultValue="true" android:defaultValue="true"
android:icon="@drawable/ic_network_wifi"
android:key="wifi_only" android:key="wifi_only"
android:summary="@string/wifi_only_summary" android:summary="@string/wifi_only_summary"
android:title="@string/wifi_only" /> android:title="@string/wifi_only" />
<SwitchPreferenceCompat <SwitchPreferenceCompat
android:defaultValue="false" android:defaultValue="false"
android:icon="@drawable/ic_battery_charging"
android:key="require_charging" android:key="require_charging"
android:summary="@string/require_charging_summary" android:summary="@string/require_charging_summary"
android:title="@string/require_charging" /> android:title="@string/require_charging" />
<SwitchPreferenceCompat <SwitchPreferenceCompat
android:defaultValue="true" android:defaultValue="true"
android:icon="@drawable/ic_check_all"
android:key="request_acknowledgements" android:key="request_acknowledgements"
android:summary="@string/request_acknowledgements_summary" android:summary="@string/request_acknowledgements_summary"
android:title="@string/request_acknowledgements" /> android:title="@string/request_acknowledgements" />
</PreferenceScreen> </PreferenceCategory>
<PreferenceScreen <PreferenceCategory android:title="@string/preference_group_advanced">
android:key="preference_advanced"
android:persistent="false"
android:summary="@string/preference_group_advanced_summary"
android:title="@string/preference_group_advanced">
<Preference <Preference
android:icon="@drawable/ic_broom"
android:key="cleanup" android:key="cleanup"
android:summary="@string/cleanup_summary" android:summary="@string/cleanup_summary"
android:title="@string/cleanup" /> android:title="@string/cleanup" />
<Preference <Preference
android:icon="@drawable/ic_export"
android:key="export" android:key="export"
android:summary="@string/export_data_summary" android:summary="@string/export_data_summary"
android:title="@string/export_data" /> android:title="@string/export_data" />
<Preference <Preference
android:icon="@drawable/ic_import"
android:key="import" android:key="import"
android:summary="@string/import_data_summary" android:summary="@string/import_data_summary"
android:title="@string/import_data" /> android:title="@string/import_data" />
<Preference <Preference
android:icon="@drawable/ic_bug_report"
android:key="status" android:key="status"
android:summary="@string/status_summary" android:summary="@string/status_summary"
android:title="@string/status" /> android:title="@string/status" />
<EditTextPreference <EditTextPreference
android:defaultValue="8444" android:defaultValue="8444"
android:icon="@drawable/ic_port"
android:key="listening_port" android:key="listening_port"
android:numeric="integer"
android:summary="@string/preference_port_summary" android:summary="@string/preference_port_summary"
android:title="@string/preference_port" android:title="@string/preference_port" />
android:numeric="integer"/>
</PreferenceScreen> </PreferenceCategory>
<PreferenceCategory android:title="@string/preference_group_app">
<Preference <Preference
android:icon="@drawable/ic_info"
android:key="about" android:key="about"
android:summary="@string/about_summary" android:summary="@string/about_summary"
android:title="@string/about" /> android:title="@string/about" />
<Preference <Preference
android:icon="@drawable/ic_support_app"
android:key="help_out" android:key="help_out"
android:summary="@string/help_out_summary" android:summary="@string/help_out_summary"
android:title="@string/help_out"> android:title="@string/help_out">
@ -94,4 +96,5 @@
android:action="android.intent.action.VIEW" android:action="android.intent.action.VIEW"
android:data="@string/help_out_link" /> android:data="@string/help_out_link" />
</Preference> </Preference>
</PreferenceCategory>
</PreferenceScreen> </PreferenceScreen>

View File

@ -21,6 +21,7 @@ import ch.dissem.apps.abit.repository.AndroidAddressRepository
import ch.dissem.apps.abit.repository.AndroidLabelRepository import ch.dissem.apps.abit.repository.AndroidLabelRepository
import ch.dissem.apps.abit.repository.AndroidMessageRepository import ch.dissem.apps.abit.repository.AndroidMessageRepository
import ch.dissem.apps.abit.repository.SqlHelper import ch.dissem.apps.abit.repository.SqlHelper
import ch.dissem.apps.abit.util.preferences
import ch.dissem.bitmessage.cryptography.bc.BouncyCryptography import ch.dissem.bitmessage.cryptography.bc.BouncyCryptography
import ch.dissem.bitmessage.entity.BitmessageAddress import ch.dissem.bitmessage.entity.BitmessageAddress
import ch.dissem.bitmessage.entity.ObjectMessage import ch.dissem.bitmessage.entity.ObjectMessage
@ -67,7 +68,7 @@ class AndroidMessageRepositoryTest : TestBase() {
val addressRepo = AndroidAddressRepository(sqlHelper) val addressRepo = AndroidAddressRepository(sqlHelper)
val labelRepo = AndroidLabelRepository(sqlHelper, RuntimeEnvironment.application) val labelRepo = AndroidLabelRepository(sqlHelper, RuntimeEnvironment.application)
repo = AndroidMessageRepository(sqlHelper) repo = AndroidMessageRepository(sqlHelper, RuntimeEnvironment.application.preferences)
mockedInternalContext( mockedInternalContext(
cryptography = BouncyCryptography(), cryptography = BouncyCryptography(),
addressRepository = addressRepo, addressRepository = addressRepo,

View File

@ -18,6 +18,7 @@ package ch.dissem.bitmessage.repository
import android.os.Build.VERSION_CODES.LOLLIPOP import android.os.Build.VERSION_CODES.LOLLIPOP
import ch.dissem.apps.abit.repository.* import ch.dissem.apps.abit.repository.*
import ch.dissem.apps.abit.util.preferences
import ch.dissem.bitmessage.entity.BitmessageAddress import ch.dissem.bitmessage.entity.BitmessageAddress
import ch.dissem.bitmessage.entity.ObjectMessage import ch.dissem.bitmessage.entity.ObjectMessage
import ch.dissem.bitmessage.entity.Plaintext import ch.dissem.bitmessage.entity.Plaintext
@ -60,7 +61,7 @@ class AndroidProofOfWorkRepositoryTest : TestBase() {
RuntimeEnvironment.application.deleteDatabase(SqlHelper.DATABASE_NAME) RuntimeEnvironment.application.deleteDatabase(SqlHelper.DATABASE_NAME)
val sqlHelper = SqlHelper(RuntimeEnvironment.application) val sqlHelper = SqlHelper(RuntimeEnvironment.application)
addressRepo = AndroidAddressRepository(sqlHelper) addressRepo = AndroidAddressRepository(sqlHelper)
messageRepo = AndroidMessageRepository(sqlHelper) messageRepo = AndroidMessageRepository(sqlHelper, RuntimeEnvironment.application.preferences)
repo = AndroidProofOfWorkRepository(sqlHelper) repo = AndroidProofOfWorkRepository(sqlHelper)
mockedInternalContext( mockedInternalContext(
addressRepository = addressRepo, addressRepository = addressRepo,

View File

@ -1,12 +1,12 @@
buildscript { buildscript {
ext.kotlin_version = '1.2.51' ext.kotlin_version = '1.2.71'
ext.anko_version = '0.10.5' ext.anko_version = '0.10.5'
repositories { repositories {
jcenter()
google() google()
jcenter()
} }
dependencies { dependencies {
classpath 'com.android.tools.build:gradle:3.1.3' classpath 'com.android.tools.build:gradle:3.2.1'
classpath "org.jetbrains.kotlin:kotlin-gradle-plugin:$kotlin_version" classpath "org.jetbrains.kotlin:kotlin-gradle-plugin:$kotlin_version"
classpath 'com.github.ben-manes:gradle-versions-plugin:0.20.0' classpath 'com.github.ben-manes:gradle-versions-plugin:0.20.0'
@ -21,7 +21,6 @@ allprojects {
repositories { repositories {
google() google()
jcenter() jcenter()
mavenCentral()
maven { url 'https://oss.sonatype.org/content/repositories/snapshots/' } maven { url 'https://oss.sonatype.org/content/repositories/snapshots/' }
maven { url "https://jitpack.io" } maven { url "https://jitpack.io" }
} }

View File

@ -10,6 +10,8 @@
# Specifies the JVM arguments used for the daemon process. # Specifies the JVM arguments used for the daemon process.
# The setting is particularly useful for tweaking memory settings. # The setting is particularly useful for tweaking memory settings.
# Default value: -Xmx10248m -XX:MaxPermSize=256m # Default value: -Xmx10248m -XX:MaxPermSize=256m
android.enableJetifier=true
android.useAndroidX=true
org.gradle.jvmargs=-Xmx2048m -XX:MaxPermSize=512m -XX:+HeapDumpOnOutOfMemoryError -Dfile.encoding=UTF-8 org.gradle.jvmargs=-Xmx2048m -XX:MaxPermSize=512m -XX:+HeapDumpOnOutOfMemoryError -Dfile.encoding=UTF-8
# When configured, Gradle will run in incubating parallel mode. # When configured, Gradle will run in incubating parallel mode.

View File

@ -1,6 +1,6 @@
#Sat Mar 03 14:35:52 CET 2018 #Tue Aug 28 16:14:32 CEST 2018
distributionBase=GRADLE_USER_HOME distributionBase=GRADLE_USER_HOME
distributionPath=wrapper/dists distributionPath=wrapper/dists
zipStoreBase=GRADLE_USER_HOME zipStoreBase=GRADLE_USER_HOME
zipStorePath=wrapper/dists zipStorePath=wrapper/dists
distributionUrl=https\://services.gradle.org/distributions/gradle-4.5-all.zip distributionUrl=https\://services.gradle.org/distributions/gradle-4.6-all.zip