🤯 Update dependencies, switch to AndroidX
This commit is contained in:
parent
e67a4ea71b
commit
0405d9e04f
@ -13,8 +13,8 @@ if (project.hasProperty("project.configs")
|
||||
|
||||
//noinspection GroovyMissingReturnStatement
|
||||
android {
|
||||
compileSdkVersion 27
|
||||
buildToolsVersion "27.0.3"
|
||||
compileSdkVersion 28
|
||||
buildToolsVersion "28.0.3"
|
||||
|
||||
signingConfigs {
|
||||
release
|
||||
@ -22,7 +22,7 @@ android {
|
||||
defaultConfig {
|
||||
applicationId "ch.dissem.apps.${appName.toLowerCase()}"
|
||||
minSdkVersion 21
|
||||
targetSdkVersion 27
|
||||
targetSdkVersion 28
|
||||
versionCode 23
|
||||
versionName "1.0-rc1"
|
||||
multiDexEnabled true
|
||||
@ -62,13 +62,16 @@ dependencies {
|
||||
implementation "org.jetbrains.kotlin:kotlin-reflect:$kotlin_version"
|
||||
implementation "org.jetbrains.anko:anko:$anko_version"
|
||||
|
||||
implementation "com.android.support:appcompat-v7:$supportVersion"
|
||||
implementation "com.android.support:preference-v7:$supportVersion"
|
||||
implementation "com.android.support:cardview-v7:$supportVersion"
|
||||
implementation "com.android.support:support-v13:$supportVersion"
|
||||
implementation "com.android.support:preference-v14:$supportVersion"
|
||||
implementation "com.android.support:design:$supportVersion"
|
||||
implementation "com.android.support:multidex:1.0.3"
|
||||
implementation 'androidx.appcompat:appcompat:1.0.0'
|
||||
implementation 'androidx.preference:preference:1.0.0'
|
||||
implementation 'androidx.cardview:cardview:1.0.0'
|
||||
implementation 'androidx.legacy:legacy-support-v13:1.0.0'
|
||||
implementation 'androidx.legacy:legacy-preference-v14:1.0.0'
|
||||
implementation 'com.google.android.material:material:1.0.0'
|
||||
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-networking:$jabitVersion"
|
||||
@ -80,15 +83,15 @@ dependencies {
|
||||
|
||||
implementation 'org.slf4j:slf4j-android:1.7.25'
|
||||
|
||||
implementation 'com.mikepenz:materialize:1.1.2@aar'
|
||||
implementation('com.mikepenz:materialdrawer:6.0.8@aar') {
|
||||
implementation 'com.mikepenz:materialize:1.2.0-rc01@aar'
|
||||
implementation('com.mikepenz:materialdrawer:6.1.0-rc01.2@aar') {
|
||||
transitive = true
|
||||
}
|
||||
implementation('com.mikepenz:aboutlibraries:6.0.9@aar') {
|
||||
implementation('com.mikepenz:aboutlibraries:6.2.0-rc01@aar') {
|
||||
transitive = true
|
||||
}
|
||||
implementation "com.mikepenz:iconics-core:3.0.4@aar"
|
||||
implementation "com.mikepenz:iconics-views:3.0.4@aar"
|
||||
implementation "com.mikepenz:iconics-core:3.1.0-rc01@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:community-material-typeface:2.0.46.1@aar'
|
||||
|
||||
@ -97,11 +100,12 @@ dependencies {
|
||||
|
||||
implementation 'com.github.kobakei:MaterialFabSpeedDial:1.2.0'
|
||||
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.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 'org.mockito:mockito-core:2.19.0'
|
||||
@ -111,7 +115,7 @@ dependencies {
|
||||
testImplementation 'org.robolectric:robolectric: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 {
|
||||
|
@ -11,9 +11,10 @@
|
||||
<uses-permission android:name="android.permission.AUTHENTICATE_ACCOUNTS" />
|
||||
<uses-permission android:name="android.permission.READ_SYNC_SETTINGS" />
|
||||
<uses-permission android:name="android.permission.WRITE_SYNC_SETTINGS" />
|
||||
<uses-permission android:name="android.permission.FOREGROUND_SERVICE" />
|
||||
|
||||
<application
|
||||
android:name="android.support.multidex.MultiDexApplication"
|
||||
android:name="androidx.multidex.MultiDexApplication"
|
||||
android:allowBackup="false"
|
||||
android:icon="@mipmap/ic_launcher"
|
||||
android:label="@string/app_name"
|
||||
@ -124,7 +125,7 @@
|
||||
|
||||
<!-- Exports -->
|
||||
<provider
|
||||
android:name="android.support.v4.content.FileProvider"
|
||||
android:name="androidx.core.content.FileProvider"
|
||||
android:authorities="ch.dissem.apps.abit.fileprovider"
|
||||
android:exported="false"
|
||||
android:grantUriPermissions="true">
|
||||
|
@ -18,7 +18,7 @@ package ch.dissem.apps.abit
|
||||
|
||||
import android.content.Context
|
||||
import android.os.Bundle
|
||||
import android.support.v4.app.ListFragment
|
||||
import androidx.fragment.app.ListFragment
|
||||
import android.view.View
|
||||
import android.widget.ListView
|
||||
|
||||
|
@ -19,7 +19,7 @@ package ch.dissem.apps.abit
|
||||
import android.app.AlertDialog
|
||||
import android.content.Intent
|
||||
import android.os.Bundle
|
||||
import android.support.v4.app.Fragment
|
||||
import androidx.fragment.app.Fragment
|
||||
import android.text.Editable
|
||||
import android.text.TextWatcher
|
||||
import android.view.*
|
||||
|
@ -28,7 +28,6 @@ import android.widget.ImageView
|
||||
import android.widget.TextView
|
||||
import ch.dissem.apps.abit.service.Singleton
|
||||
import ch.dissem.bitmessage.entity.BitmessageAddress
|
||||
import com.google.zxing.integration.android.IntentIntegrator
|
||||
import io.github.kobakei.materialfabspeeddial.FabSpeedDialMenu
|
||||
import org.jetbrains.anko.doAsync
|
||||
import org.jetbrains.anko.uiThread
|
||||
@ -44,7 +43,7 @@ class AddressListFragment : AbstractItemListFragment<Void, BitmessageAddress>()
|
||||
super.onCreate(savedInstanceState)
|
||||
|
||||
adapter = object : ArrayAdapter<BitmessageAddress>(
|
||||
activity,
|
||||
activity!!,
|
||||
R.layout.subscription_row,
|
||||
R.id.name,
|
||||
LinkedList()
|
||||
@ -109,9 +108,10 @@ class AddressListFragment : AbstractItemListFragment<Void, BitmessageAddress>()
|
||||
activity.initFab(R.drawable.ic_action_add_contact, menu)
|
||||
.addOnMenuItemClickListener { _, _, itemId ->
|
||||
when (itemId) {
|
||||
1 -> IntentIntegrator.forSupportFragment(this@AddressListFragment)
|
||||
.setDesiredBarcodeFormats(IntentIntegrator.QR_CODE)
|
||||
.initiateScan()
|
||||
// FIXME
|
||||
// 1 -> IntentIntegrator.forSupportFragment(this@AddressListFragment)
|
||||
// .setDesiredBarcodeFormats(IntentIntegrator.QR_CODE)
|
||||
// .initiateScan()
|
||||
2 -> {
|
||||
val intent = Intent(getActivity(), CreateAddressActivity::class.java)
|
||||
startActivity(intent)
|
||||
|
@ -20,8 +20,8 @@ import android.app.Activity
|
||||
import android.content.Context
|
||||
import android.content.Intent
|
||||
import android.os.Bundle
|
||||
import android.support.v4.app.Fragment
|
||||
import android.support.v7.app.AppCompatActivity
|
||||
import androidx.fragment.app.Fragment
|
||||
import androidx.appcompat.app.AppCompatActivity
|
||||
import ch.dissem.apps.abit.service.Singleton
|
||||
import ch.dissem.bitmessage.entity.Plaintext
|
||||
import ch.dissem.bitmessage.entity.Plaintext.Encoding.EXTENDED
|
||||
|
@ -20,7 +20,7 @@ import android.app.Activity.RESULT_OK
|
||||
import android.content.Context
|
||||
import android.content.Intent
|
||||
import android.os.Bundle
|
||||
import android.support.v4.app.Fragment
|
||||
import androidx.fragment.app.Fragment
|
||||
import android.view.*
|
||||
import android.widget.AdapterView
|
||||
import android.widget.Toast
|
||||
@ -89,10 +89,10 @@ class ComposeMessageFragment : Fragment() {
|
||||
recipient = getSerializable(EXTRA_RECIPIENT) as BitmessageAddress
|
||||
}
|
||||
if (containsKey(EXTRA_SUBJECT)) {
|
||||
subject = getString(EXTRA_SUBJECT)
|
||||
subject = getString(EXTRA_SUBJECT) ?: throw IllegalStateException("EXTRA_SUBJECT expected")
|
||||
}
|
||||
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
|
||||
|
||||
|
@ -17,8 +17,8 @@
|
||||
package ch.dissem.apps.abit
|
||||
|
||||
import android.os.Bundle
|
||||
import android.support.v4.app.Fragment
|
||||
import android.support.v7.widget.LinearLayoutManager
|
||||
import androidx.fragment.app.Fragment
|
||||
import androidx.recyclerview.widget.LinearLayoutManager
|
||||
import android.view.*
|
||||
import ch.dissem.apps.abit.adapter.ConversationAdapter
|
||||
import ch.dissem.apps.abit.service.Singleton
|
||||
@ -74,8 +74,7 @@ class ConversationDetailFragment : Fragment() {
|
||||
item?.let { item ->
|
||||
subject.text = item.subject
|
||||
avatar.setImageDrawable(MultiIdenticon(item.participants))
|
||||
messages.adapter =
|
||||
ConversationAdapter(ctx, this@ConversationDetailFragment, item, Singleton.currentLabel.value)
|
||||
messages.adapter = ConversationAdapter(ctx, this@ConversationDetailFragment, item, Singleton.currentLabel)
|
||||
messages.layoutManager = LinearLayoutManager(activity)
|
||||
}
|
||||
}
|
||||
|
@ -19,36 +19,29 @@ package ch.dissem.apps.abit
|
||||
|
||||
import android.content.Intent
|
||||
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.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_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.listener.ListSelectionListener
|
||||
import ch.dissem.apps.abit.repository.AndroidMessageRepository
|
||||
import ch.dissem.apps.abit.service.Singleton
|
||||
import ch.dissem.apps.abit.service.Singleton.currentLabel
|
||||
import ch.dissem.apps.abit.util.preferences
|
||||
import ch.dissem.bitmessage.entity.Conversation
|
||||
import ch.dissem.bitmessage.entity.valueobject.Label
|
||||
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.reactivex.disposables.Disposable
|
||||
import kotlinx.android.synthetic.main.fragment_message_list.*
|
||||
import org.jetbrains.anko.cancelButton
|
||||
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 org.jetbrains.anko.*
|
||||
import java.util.*
|
||||
|
||||
private const val PAGE_SIZE = 15
|
||||
@ -70,12 +63,9 @@ class ConversationListFragment : Fragment(), ListHolder<Label> {
|
||||
|
||||
private var layoutManager: LinearLayoutManager? = 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() {
|
||||
override fun onScrolled(recyclerView: RecyclerView?, dx: Int, dy: Int) {
|
||||
override fun onScrolled(recyclerView: RecyclerView, dx: Int, dy: Int) {
|
||||
layoutManager?.let { layoutManager ->
|
||||
val visibleItemCount = layoutManager.childCount
|
||||
val totalItemCount = layoutManager.itemCount
|
||||
@ -98,6 +88,13 @@ class ConversationListFragment : Fragment(), ListHolder<Label> {
|
||||
private lateinit var conversationService: ConversationService
|
||||
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>()
|
||||
|
||||
fun loadMoreItems() {
|
||||
@ -112,7 +109,7 @@ class ConversationListFragment : Fragment(), ListHolder<Label> {
|
||||
)
|
||||
conversationIds.forEach { conversationId ->
|
||||
val conversation = conversationService.getConversation(conversationId)
|
||||
onUiThread {
|
||||
uiThread {
|
||||
messageAdapter.add(conversation)
|
||||
}
|
||||
}
|
||||
@ -135,12 +132,12 @@ class ConversationListFragment : Fragment(), ListHolder<Label> {
|
||||
messageRepo = Singleton.getMessageRepository(activity)
|
||||
conversationService = Singleton.getConversationService(activity)
|
||||
|
||||
currentLabel.addObserver(this) { new -> doUpdateList(new) }
|
||||
subscription = currentLabel.subscribe { new -> doUpdateList(new) }
|
||||
doUpdateList(currentLabel.value)
|
||||
}
|
||||
|
||||
override fun onPause() {
|
||||
currentLabel.removeObserver(this)
|
||||
subscription?.dispose()
|
||||
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
|
||||
deleteAllMenuItem?.isVisible = false
|
||||
|
||||
mainActivity?.apply {
|
||||
MainActivity.apply {
|
||||
if ("archive" == label.toString()) {
|
||||
updateTitle(getString(R.string.archive))
|
||||
} else {
|
||||
@ -181,75 +178,57 @@ class ConversationListFragment : Fragment(), ListHolder<Label> {
|
||||
|
||||
val context = context ?: throw IllegalStateException("No context available")
|
||||
|
||||
layoutManager = LinearLayoutManager(context, LinearLayoutManager.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()
|
||||
|
||||
//swipeableConversationAdapter
|
||||
val adapter = SwipeableConversationAdapter(context).apply {
|
||||
setActivateOnItemClick(activateOnItemClick)
|
||||
}
|
||||
adapter.eventListener = object : SwipeableConversationAdapter.EventListener {
|
||||
override fun onItemDeleted(item: Conversation) {
|
||||
val listener = object : EventListener {
|
||||
override fun onItemDeleted(position: Int) {
|
||||
swipeableConversationAdapter?.getItem(position)?.let { item ->
|
||||
item.messages.forEach {
|
||||
Singleton.labeler.delete(it)
|
||||
messageRepo.save(it)
|
||||
}
|
||||
}
|
||||
|
||||
override fun onItemArchived(item: Conversation) {
|
||||
item.messages.forEach { Singleton.labeler.archive(it) }
|
||||
swipeableConversationAdapter?.removeAt(position)
|
||||
|
||||
}
|
||||
|
||||
override fun onItemViewClicked(v: View?) {
|
||||
val position = recycler_view.getChildAdapterPosition(v)
|
||||
adapter.setSelectedPosition(position)
|
||||
override fun onItemArchived(position: Int) {
|
||||
swipeableConversationAdapter?.getItem(position)?.let { item ->
|
||||
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) {
|
||||
MainActivity.apply { onItemSelected(adapter.getItem(position)) }
|
||||
swipeableConversationAdapter?.getItem(position)?.let { item ->
|
||||
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
|
||||
|
||||
}
|
||||
layoutManager = LinearLayoutManager(context, RecyclerView.VERTICAL, false)
|
||||
recycler_view.layoutManager = layoutManager
|
||||
recycler_view.adapter = wrappedAdapter // requires *wrapped* swipeableConversationAdapter
|
||||
recycler_view.itemAnimator = animator
|
||||
swipeableConversationAdapter = SwipeableConversationAdapter(context).apply {
|
||||
activateOnItemClick = this@ConversationListFragment.activateOnItemClick
|
||||
eventListener = listener
|
||||
}
|
||||
recycler_view.adapter = swipeableConversationAdapter
|
||||
recycler_view.addOnScrollListener(recyclerViewOnScrollListener)
|
||||
|
||||
recycler_view.addItemDecoration(
|
||||
SimpleListDividerDecorator(
|
||||
ContextCompat.getDrawable(context, R.drawable.list_divider_h), true
|
||||
)
|
||||
)
|
||||
val dirs = when (currentLabel.value?.type) {
|
||||
Label.Type.TRASH -> ItemTouchHelper.LEFT
|
||||
else -> ItemTouchHelper.LEFT + ItemTouchHelper.RIGHT
|
||||
}
|
||||
|
||||
// NOTE:
|
||||
// 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)
|
||||
val swipeHandler = SwipeToDeleteCallback(context, dirs, listener)
|
||||
|
||||
recyclerViewTouchActionGuardManager = touchActionGuardManager
|
||||
recyclerViewSwipeManager = swipeManager
|
||||
swipeableConversationAdapter = adapter
|
||||
val itemTouchHelper = ItemTouchHelper(swipeHandler)
|
||||
itemTouchHelper.attachToRecyclerView(recycler_view)
|
||||
|
||||
// FIXME Singleton.updateMessageListAdapterInListener(adapter)
|
||||
}
|
||||
@ -287,18 +266,6 @@ class ConversationListFragment : Fragment(), ListHolder<Label> {
|
||||
}
|
||||
|
||||
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
|
||||
layoutManager = null
|
||||
|
||||
@ -324,9 +291,10 @@ class ConversationListFragment : Fragment(), ListHolder<Label> {
|
||||
}
|
||||
R.id.delete_all -> {
|
||||
currentLabel.value?.let { label ->
|
||||
context?.apply {
|
||||
alert(
|
||||
title = R.string.delete_all_messages_in_list,
|
||||
message = R.string.delete_all_messages_in_list_ask
|
||||
R.string.delete_all_messages_in_list,
|
||||
R.string.delete_all_messages_in_list_ask
|
||||
) {
|
||||
positiveButton(R.string.delete) {
|
||||
deleteAllMessages(label)
|
||||
@ -334,6 +302,7 @@ class ConversationListFragment : Fragment(), ListHolder<Label> {
|
||||
cancelButton { }
|
||||
}.show()
|
||||
}
|
||||
}
|
||||
return true
|
||||
}
|
||||
else -> return false
|
||||
@ -351,18 +320,13 @@ class ConversationListFragment : Fragment(), ListHolder<Label> {
|
||||
}
|
||||
|
||||
override fun updateList(label: Label) {
|
||||
currentLabel.value = label
|
||||
}
|
||||
|
||||
override fun setActivateOnItemClick(activateOnItemClick: Boolean) {
|
||||
swipeableConversationAdapter?.setActivateOnItemClick(activateOnItemClick)
|
||||
this.activateOnItemClick = activateOnItemClick
|
||||
currentLabel.onNext(label)
|
||||
}
|
||||
|
||||
override fun showPreviousList() = if (backStack.isEmpty()) {
|
||||
false
|
||||
} else {
|
||||
currentLabel.value = backStack.pop()
|
||||
currentLabel.onNext(backStack.pop())
|
||||
true
|
||||
}
|
||||
}
|
||||
|
@ -19,7 +19,7 @@ package ch.dissem.apps.abit
|
||||
import android.app.Activity
|
||||
import android.net.Uri
|
||||
import android.os.Bundle
|
||||
import android.support.v7.app.AppCompatActivity
|
||||
import androidx.appcompat.app.AppCompatActivity
|
||||
import android.util.Base64
|
||||
import android.util.Base64.URL_SAFE
|
||||
import android.widget.Button
|
||||
|
@ -2,8 +2,8 @@ package ch.dissem.apps.abit
|
||||
|
||||
import android.content.Intent
|
||||
import android.os.Bundle
|
||||
import android.support.v4.app.NavUtils
|
||||
import android.support.v7.app.AppCompatActivity
|
||||
import androidx.core.app.NavUtils
|
||||
import androidx.appcompat.app.AppCompatActivity
|
||||
import android.view.MenuItem
|
||||
import com.mikepenz.materialize.MaterializeBuilder
|
||||
import kotlinx.android.synthetic.main.scrolling_toolbar_layout.*
|
||||
|
@ -18,7 +18,7 @@ package ch.dissem.apps.abit
|
||||
|
||||
import android.graphics.*
|
||||
import android.graphics.drawable.Drawable
|
||||
import android.support.annotation.ColorInt
|
||||
import androidx.annotation.ColorInt
|
||||
import android.text.TextPaint
|
||||
import ch.dissem.bitmessage.entity.BitmessageAddress
|
||||
import org.jetbrains.anko.collections.forEachWithIndex
|
||||
@ -68,8 +68,8 @@ class Identicon(input: BitmessageAddress) : Drawable() {
|
||||
}
|
||||
|
||||
override fun draw(canvas: Canvas) {
|
||||
val width = canvas.width.toFloat()
|
||||
val height = canvas.height.toFloat()
|
||||
val width = bounds.width().toFloat()
|
||||
val height = bounds.height().toFloat()
|
||||
draw(canvas, 0f, 0f, width, height)
|
||||
}
|
||||
|
||||
@ -124,11 +124,11 @@ class MultiIdenticon(input: List<BitmessageAddress>, @ColorInt private val backg
|
||||
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) {
|
||||
val width = canvas.width.toFloat()
|
||||
val height = canvas.height.toFloat()
|
||||
val width = bounds.width().toFloat()
|
||||
val height = bounds.height().toFloat()
|
||||
|
||||
when (identicons.size) {
|
||||
0 -> canvas.drawCircle(width / 2, height / 2, width / 2, paint)
|
||||
|
@ -16,19 +16,18 @@
|
||||
|
||||
package ch.dissem.apps.abit
|
||||
|
||||
import android.app.Fragment
|
||||
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.View
|
||||
import android.view.ViewGroup
|
||||
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.service.Singleton
|
||||
import ch.dissem.bitmessage.wif.WifImporter
|
||||
import com.h6ah4i.android.widget.advrecyclerview.decoration.SimpleListDividerDecorator
|
||||
import org.ini4j.InvalidFileFormatException
|
||||
import org.jetbrains.anko.longToast
|
||||
|
||||
@ -47,34 +46,31 @@ class ImportIdentitiesFragment : Fragment() {
|
||||
inflater.inflate(R.layout.fragment_import_select_identities, container, false)
|
||||
|
||||
override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
|
||||
val ctx = activity ?: throw IllegalStateException("No activity available")
|
||||
super.onViewCreated(view, savedInstanceState)
|
||||
|
||||
val wifData = arguments.getString(WIF_DATA)
|
||||
val bmc = Singleton.getBitmessageContext(activity)
|
||||
val wifData = arguments?.getString(WIF_DATA) ?: throw IllegalStateException("No WIF data")
|
||||
val bmc = Singleton.getBitmessageContext(ctx)
|
||||
|
||||
try {
|
||||
importer = WifImporter(bmc, wifData)
|
||||
} catch (e: InvalidFileFormatException) {
|
||||
longToast(R.string.invalid_wif_file)
|
||||
activity.finish()
|
||||
ctx.longToast(R.string.invalid_wif_file)
|
||||
ctx.finish()
|
||||
return
|
||||
}
|
||||
|
||||
adapter = AddressSelectorAdapter(importer.getIdentities())
|
||||
val layoutManager = LinearLayoutManager(
|
||||
activity,
|
||||
LinearLayoutManager.VERTICAL,
|
||||
RecyclerView.VERTICAL,
|
||||
false
|
||||
)
|
||||
val recyclerView = view.findViewById<RecyclerView>(R.id.recycler_view)
|
||||
recyclerView.layoutManager = layoutManager
|
||||
recyclerView.adapter = adapter
|
||||
|
||||
recyclerView.addItemDecoration(
|
||||
SimpleListDividerDecorator(
|
||||
ContextCompat.getDrawable(activity, R.drawable.list_divider_h), true
|
||||
)
|
||||
)
|
||||
recyclerView.addItemDecoration(DividerItemDecoration(ctx, DividerItemDecoration.HORIZONTAL))
|
||||
|
||||
view.findViewById<Button>(R.id.finish).setOnClickListener {
|
||||
importer.importAll(adapter.selected)
|
||||
@ -83,7 +79,7 @@ class ImportIdentitiesFragment : Fragment() {
|
||||
addIdentityEntry(selected)
|
||||
}
|
||||
}
|
||||
activity.finish()
|
||||
ctx.finish()
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -17,6 +17,7 @@
|
||||
package ch.dissem.apps.abit
|
||||
|
||||
import android.os.Bundle
|
||||
import androidx.fragment.app.transaction
|
||||
|
||||
/**
|
||||
* @author Christian Basler
|
||||
@ -29,19 +30,20 @@ class ImportIdentityActivity : DetailActivity() {
|
||||
val wifData: String? = savedInstanceState?.getString(ImportIdentitiesFragment.WIF_DATA)
|
||||
|
||||
if (wifData == null) {
|
||||
fragmentManager.beginTransaction()
|
||||
.replace(R.id.content, InputWifFragment())
|
||||
.commit()
|
||||
supportFragmentManager.transaction {
|
||||
replace(R.id.content, InputWifFragment())
|
||||
}
|
||||
} else {
|
||||
val bundle = Bundle()
|
||||
bundle.putString(ImportIdentitiesFragment.WIF_DATA, wifData)
|
||||
|
||||
val fragment = ImportIdentitiesFragment()
|
||||
fragment.arguments = bundle
|
||||
val fragment = ImportIdentitiesFragment().apply {
|
||||
arguments = bundle
|
||||
}
|
||||
|
||||
fragmentManager.beginTransaction()
|
||||
.replace(R.id.content, fragment)
|
||||
.commit()
|
||||
supportFragmentManager.transaction {
|
||||
replace(R.id.content, fragment)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -16,10 +16,11 @@
|
||||
|
||||
package ch.dissem.apps.abit
|
||||
|
||||
import android.app.Fragment
|
||||
import android.os.Bundle
|
||||
import android.view.*
|
||||
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.DialogProperties
|
||||
import com.github.angads25.filepicker.view.FilePickerDialog
|
||||
@ -42,7 +43,7 @@ class InputWifFragment : Fragment() {
|
||||
override fun onCreateView(inflater: LayoutInflater, container: ViewGroup?, savedInstanceState: Bundle?): View =
|
||||
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)
|
||||
next.setOnClickListener {
|
||||
val bundle = Bundle()
|
||||
@ -52,9 +53,9 @@ class InputWifFragment : Fragment() {
|
||||
arguments = bundle
|
||||
}
|
||||
|
||||
fragmentManager.beginTransaction()
|
||||
.replace(R.id.content, fragment)
|
||||
.commit()
|
||||
fragmentManager?.transaction {
|
||||
replace(R.id.content, fragment)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -20,11 +20,12 @@ import android.content.Intent
|
||||
import android.graphics.Canvas
|
||||
import android.graphics.Paint
|
||||
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 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.ProfileSelectionListener
|
||||
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.service.Singleton
|
||||
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.entity.BitmessageAddress
|
||||
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 io.github.kobakei.materialfabspeeddial.FabSpeedDial
|
||||
import io.github.kobakei.materialfabspeeddial.FabSpeedDialMenu
|
||||
import io.reactivex.disposables.Disposable
|
||||
import kotlinx.android.synthetic.main.activity_main.*
|
||||
import org.jetbrains.anko.doAsync
|
||||
import org.jetbrains.anko.uiThread
|
||||
@ -92,6 +97,8 @@ class MainActivity : AppCompatActivity(), ListSelectionListener<Serializable> {
|
||||
var hasDetailPane: Boolean = false
|
||||
private set
|
||||
|
||||
private var subscription: Disposable? = null
|
||||
|
||||
private lateinit var bmc: BitmessageContext
|
||||
private lateinit var messageRepo: AndroidMessageRepository
|
||||
private lateinit var accountHeader: AccountHeader
|
||||
@ -294,11 +301,11 @@ class MainActivity : AppCompatActivity(), ListSelectionListener<Serializable> {
|
||||
|
||||
uiThread {
|
||||
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) {
|
||||
currentLabel.value = labels[0]
|
||||
|
||||
currentLabel.onNext(labels[0])
|
||||
}
|
||||
|
||||
for (label in labels) {
|
||||
addLabelEntry(label)
|
||||
}
|
||||
@ -322,7 +329,7 @@ class MainActivity : AppCompatActivity(), ListSelectionListener<Serializable> {
|
||||
val itemList = supportFragmentManager.findFragmentById(R.id.item_list)
|
||||
val tag = item.tag
|
||||
if (tag is Label) {
|
||||
currentLabel.value = tag
|
||||
currentLabel.onNext(tag)
|
||||
if (tag.type == Label.Type.INBOX || tag == LABEL_ARCHIVE) {
|
||||
if (itemList !is ConversationListFragment) {
|
||||
changeList(ConversationListFragment())
|
||||
@ -344,11 +351,10 @@ class MainActivity : AppCompatActivity(), ListSelectionListener<Serializable> {
|
||||
return false
|
||||
}
|
||||
R.string.settings -> {
|
||||
supportFragmentManager
|
||||
.beginTransaction()
|
||||
.replace(R.id.item_list, SettingsFragment())
|
||||
.addToBackStack(null)
|
||||
.commit()
|
||||
supportFragmentManager?.transaction {
|
||||
replace(R.id.item_list, SettingsFragment())
|
||||
addToBackStack(null)
|
||||
}
|
||||
return false
|
||||
}
|
||||
R.string.full_node -> return true
|
||||
@ -363,9 +369,9 @@ class MainActivity : AppCompatActivity(), ListSelectionListener<Serializable> {
|
||||
network.enableNode(false)
|
||||
updateUnread()
|
||||
Singleton.getMessageListener(this).resetNotification()
|
||||
currentLabel.addObserver(this) { label ->
|
||||
if (label != null && label.id is Long) {
|
||||
drawer.setSelection(label.id as Long)
|
||||
subscription = currentLabel.subscribe { label ->
|
||||
if (label.id is Long) {
|
||||
drawer.setSelection(label.id as Long, false)
|
||||
}
|
||||
}
|
||||
active = true
|
||||
@ -373,7 +379,7 @@ class MainActivity : AppCompatActivity(), ListSelectionListener<Serializable> {
|
||||
}
|
||||
|
||||
override fun onPause() {
|
||||
currentLabel.removeObserver(this)
|
||||
subscription?.dispose()
|
||||
super.onPause()
|
||||
active = false
|
||||
}
|
||||
@ -537,9 +543,8 @@ class MainActivity : AppCompatActivity(), ListSelectionListener<Serializable> {
|
||||
|
||||
fun initFab(@DrawableRes drawableRes: Int, menu: FabSpeedDialMenu): FabSpeedDial {
|
||||
val fab = floatingActionButton ?: throw IllegalStateException("Fab must not be null")
|
||||
fab.hide()
|
||||
fab.removeAllOnMenuItemClickListeners()
|
||||
fab.show()
|
||||
fab.closeMenu()
|
||||
val mainFab = fab.mainFab
|
||||
mainFab.setImageResource(drawableRes)
|
||||
fab.setMenu(menu)
|
||||
@ -551,6 +556,8 @@ class MainActivity : AppCompatActivity(), ListSelectionListener<Serializable> {
|
||||
mainFab.setImageResource(drawableRes)
|
||||
}
|
||||
}
|
||||
fab.show()
|
||||
fab.closeMenu()
|
||||
return fab
|
||||
}
|
||||
|
||||
|
@ -2,7 +2,7 @@ package ch.dissem.apps.abit
|
||||
|
||||
import android.content.Intent
|
||||
import android.os.Bundle
|
||||
import android.support.v4.app.NavUtils
|
||||
import androidx.core.app.NavUtils
|
||||
import android.view.MenuItem
|
||||
import ch.dissem.bitmessage.entity.Plaintext
|
||||
|
||||
|
@ -19,11 +19,11 @@ package ch.dissem.apps.abit
|
||||
import android.content.Context
|
||||
import android.content.Intent
|
||||
import android.os.Bundle
|
||||
import android.support.annotation.IdRes
|
||||
import android.support.v4.app.Fragment
|
||||
import android.support.v7.widget.GridLayoutManager
|
||||
import android.support.v7.widget.LinearLayoutManager
|
||||
import android.support.v7.widget.RecyclerView
|
||||
import androidx.annotation.IdRes
|
||||
import androidx.fragment.app.Fragment
|
||||
import androidx.recyclerview.widget.GridLayoutManager
|
||||
import androidx.recyclerview.widget.LinearLayoutManager
|
||||
import androidx.recyclerview.widget.RecyclerView
|
||||
import android.text.util.Linkify
|
||||
import android.text.util.Linkify.WEB_URLS
|
||||
import android.view.*
|
||||
|
@ -19,33 +19,28 @@ package ch.dissem.apps.abit
|
||||
|
||||
import android.content.Intent
|
||||
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 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 android.view.*
|
||||
import android.widget.Toast
|
||||
import ch.dissem.apps.abit.ComposeMessageActivity.Companion.EXTRA_BROADCAST
|
||||
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.listener.ListSelectionListener
|
||||
import ch.dissem.apps.abit.repository.AndroidMessageRepository
|
||||
import ch.dissem.apps.abit.service.Singleton
|
||||
import ch.dissem.apps.abit.service.Singleton.currentLabel
|
||||
import ch.dissem.apps.abit.util.preferences
|
||||
import ch.dissem.bitmessage.entity.Plaintext
|
||||
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.reactivex.disposables.Disposable
|
||||
import kotlinx.android.synthetic.main.fragment_message_list.*
|
||||
import org.jetbrains.anko.*
|
||||
import org.jetbrains.anko.support.v4.alert
|
||||
import org.jetbrains.anko.support.v4.onUiThread
|
||||
import java.util.*
|
||||
|
||||
private const val PAGE_SIZE = 15
|
||||
@ -65,21 +60,20 @@ class MessageListFragment : Fragment(), ListHolder<Label> {
|
||||
private var isLoading = false
|
||||
private var isLastPage = false
|
||||
|
||||
private var subscription: Disposable? = null
|
||||
|
||||
private var layoutManager: LinearLayoutManager? = 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() {
|
||||
override fun onScrolled(recyclerView: RecyclerView?, dx: Int, dy: Int) {
|
||||
override fun onScrolled(recyclerView: RecyclerView, dx: Int, dy: Int) {
|
||||
layoutManager?.let { layoutManager ->
|
||||
val visibleItemCount = layoutManager.childCount
|
||||
val totalItemCount = layoutManager.itemCount
|
||||
val firstVisibleItemPosition = layoutManager.findFirstVisibleItemPosition()
|
||||
|
||||
if (!isLoading && !isLastPage) {
|
||||
if (visibleItemCount + firstVisibleItemPosition >= totalItemCount - 5
|
||||
if (visibleItemCount + firstVisibleItemPosition >= totalItemCount - PAGE_SIZE
|
||||
&& firstVisibleItemPosition >= 0
|
||||
) {
|
||||
loadMoreItems()
|
||||
@ -94,6 +88,11 @@ class MessageListFragment : Fragment(), ListHolder<Label> {
|
||||
private lateinit var messageRepo: AndroidMessageRepository
|
||||
private var activateOnItemClick: Boolean = false
|
||||
|
||||
override fun setActivateOnItemClick(activateOnItemClick: Boolean) {
|
||||
swipeableMessageAdapter?.activateOnItemClick = activateOnItemClick
|
||||
this.activateOnItemClick = activateOnItemClick
|
||||
}
|
||||
|
||||
private val backStack = Stack<Label>()
|
||||
|
||||
fun loadMoreItems() {
|
||||
@ -107,7 +106,7 @@ class MessageListFragment : Fragment(), ListHolder<Label> {
|
||||
PAGE_SIZE,
|
||||
context?.preferences?.separateIdentities == true && label?.type != Label.Type.BROADCAST
|
||||
)
|
||||
onUiThread {
|
||||
uiThread {
|
||||
messageAdapter.addAll(messages)
|
||||
isLoading = false
|
||||
isLastPage = messages.size < PAGE_SIZE
|
||||
@ -128,12 +127,12 @@ class MessageListFragment : Fragment(), ListHolder<Label> {
|
||||
initFab(activity)
|
||||
messageRepo = Singleton.getMessageRepository(activity)
|
||||
|
||||
currentLabel.addObserver(this) { new -> doUpdateList(new) }
|
||||
subscription = currentLabel.subscribe { new -> doUpdateList(new) }
|
||||
doUpdateList(currentLabel.value)
|
||||
}
|
||||
|
||||
override fun onPause() {
|
||||
currentLabel.removeObserver(this)
|
||||
subscription?.dispose()
|
||||
super.onPause()
|
||||
}
|
||||
|
||||
@ -151,7 +150,7 @@ class MessageListFragment : Fragment(), ListHolder<Label> {
|
||||
return
|
||||
}
|
||||
menuItem.isVisible = label.type == Label.Type.TRASH
|
||||
mainActivity?.apply {
|
||||
MainActivity.apply {
|
||||
if ("archive" == label.toString()) {
|
||||
updateTitle(getString(R.string.archive))
|
||||
} else {
|
||||
@ -176,81 +175,37 @@ class MessageListFragment : Fragment(), ListHolder<Label> {
|
||||
|
||||
val context = context ?: throw IllegalStateException("No context available")
|
||||
|
||||
layoutManager = LinearLayoutManager(context, LinearLayoutManager.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
|
||||
|
||||
layoutManager = LinearLayoutManager(context, RecyclerView.VERTICAL, false)
|
||||
recycler_view.layoutManager = layoutManager
|
||||
recycler_view.adapter = wrappedAdapter // requires *wrapped* swipeableMessageAdapter
|
||||
recycler_view.itemAnimator = animator
|
||||
swipeableMessageAdapter = SwipeableMessageAdapter(context).apply {
|
||||
activateOnItemClick = this@MessageListFragment.activateOnItemClick
|
||||
}
|
||||
recycler_view.adapter = swipeableMessageAdapter // requires *wrapped* swipeableMessageAdapter
|
||||
recycler_view.addOnScrollListener(recyclerViewOnScrollListener)
|
||||
|
||||
recycler_view.addItemDecoration(
|
||||
SimpleListDividerDecorator(
|
||||
ContextCompat.getDrawable(context, R.drawable.list_divider_h), true
|
||||
)
|
||||
)
|
||||
val dirs = when (currentLabel.value?.type) {
|
||||
Label.Type.TRASH -> ItemTouchHelper.LEFT
|
||||
else -> ItemTouchHelper.LEFT + ItemTouchHelper.RIGHT
|
||||
}
|
||||
|
||||
// NOTE:
|
||||
// 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)
|
||||
val swipeHandler = SwipeToDeleteCallback(context, dirs, object : EventListener {
|
||||
override fun onItemDeleted(position: Int) {
|
||||
context.toast("Deleted")
|
||||
}
|
||||
|
||||
recyclerViewTouchActionGuardManager = touchActionGuardManager
|
||||
recyclerViewSwipeManager = swipeManager
|
||||
swipeableMessageAdapter = adapter
|
||||
override fun onItemArchived(position: Int) {
|
||||
context.toast("Archived")
|
||||
}
|
||||
|
||||
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) {
|
||||
@ -286,18 +241,6 @@ class MessageListFragment : Fragment(), ListHolder<Label> {
|
||||
}
|
||||
|
||||
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
|
||||
layoutManager = null
|
||||
|
||||
@ -308,7 +251,7 @@ class MessageListFragment : Fragment(), ListHolder<Label> {
|
||||
inflater.inflate(R.menu.message_list, menu)
|
||||
emptyTrashMenuItem = menu.findItem(R.id.empty_trash)
|
||||
deleteAllMenuItem = menu.findItem(R.id.delete_all)
|
||||
currentLabel.value?.let { doUpdateList(it) }
|
||||
// currentLabel.value?.let { doUpdateList(it) }
|
||||
super.onCreateOptionsMenu(menu, inflater)
|
||||
}
|
||||
|
||||
@ -324,9 +267,10 @@ class MessageListFragment : Fragment(), ListHolder<Label> {
|
||||
}
|
||||
R.id.delete_all -> {
|
||||
currentLabel.value?.let { label ->
|
||||
context?.apply {
|
||||
alert(
|
||||
title = R.string.delete_all_messages_in_list,
|
||||
message = R.string.delete_all_messages_in_list_ask
|
||||
R.string.delete_all_messages_in_list,
|
||||
R.string.delete_all_messages_in_list_ask
|
||||
) {
|
||||
positiveButton(R.string.delete) {
|
||||
deleteAllMessages(label)
|
||||
@ -334,6 +278,7 @@ class MessageListFragment : Fragment(), ListHolder<Label> {
|
||||
cancelButton { }
|
||||
}.show()
|
||||
}
|
||||
}
|
||||
return true
|
||||
}
|
||||
else -> return false
|
||||
@ -351,18 +296,13 @@ class MessageListFragment : Fragment(), ListHolder<Label> {
|
||||
}
|
||||
|
||||
override fun updateList(label: Label) {
|
||||
currentLabel.value = label
|
||||
}
|
||||
|
||||
override fun setActivateOnItemClick(activateOnItemClick: Boolean) {
|
||||
swipeableMessageAdapter?.setActivateOnItemClick(activateOnItemClick)
|
||||
this.activateOnItemClick = activateOnItemClick
|
||||
currentLabel.onNext(label)
|
||||
}
|
||||
|
||||
override fun showPreviousList() = if (backStack.isEmpty()) {
|
||||
false
|
||||
} else {
|
||||
currentLabel.value = backStack.pop()
|
||||
currentLabel.onNext(backStack.pop())
|
||||
true
|
||||
}
|
||||
}
|
||||
|
@ -23,16 +23,11 @@ import android.content.Intent
|
||||
import android.content.ServiceConnection
|
||||
import android.os.Bundle
|
||||
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 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.SimpleJob
|
||||
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.LibsBuilder
|
||||
import org.jetbrains.anko.doAsync
|
||||
import org.jetbrains.anko.support.v4.indeterminateProgressDialog
|
||||
import org.jetbrains.anko.support.v4.startActivity
|
||||
import org.jetbrains.anko.indeterminateProgressDialog
|
||||
import org.jetbrains.anko.startActivity
|
||||
import org.jetbrains.anko.uiThread
|
||||
import java.util.*
|
||||
|
||||
/**
|
||||
* @author Christian Basler
|
||||
*/
|
||||
class SettingsFragment : PreferenceFragmentCompat(), PreferenceFragmentCompat.OnPreferenceStartScreenCallback {
|
||||
class SettingsFragment : PreferenceFragmentCompat() {
|
||||
|
||||
override fun onCreatePreferences(savedInstanceState: Bundle?, rootKey: String?) {
|
||||
setPreferencesFromResource(R.xml.preferences, rootKey)
|
||||
@ -117,9 +112,9 @@ class SettingsFragment : PreferenceFragmentCompat(), PreferenceFragmentCompat.On
|
||||
}
|
||||
|
||||
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 {
|
||||
val exportDirectory = ctx.preferences.exportDirectory
|
||||
exportDirectory.mkdirs()
|
||||
@ -152,20 +147,20 @@ class SettingsFragment : PreferenceFragmentCompat(), PreferenceFragmentCompat.On
|
||||
if (activity.hasDetailPane) {
|
||||
activity.setDetailView(StatusFragment())
|
||||
} else {
|
||||
startActivity<StatusActivity>()
|
||||
activity.startActivity<StatusActivity>()
|
||||
}
|
||||
return@OnPreferenceClickListener true
|
||||
}
|
||||
|
||||
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) {
|
||||
WRITE_EXPORT_REQUEST_CODE -> ctx.preferences.cleanupExportDirectory()
|
||||
READ_IMPORT_REQUEST_CODE -> {
|
||||
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 {
|
||||
Exports.importData(data.data, ctx)
|
||||
Exports.importData(data.data!!, ctx)
|
||||
uiThread {
|
||||
dismiss()
|
||||
}
|
||||
@ -224,40 +219,41 @@ class SettingsFragment : PreferenceFragmentCompat(), PreferenceFragmentCompat.On
|
||||
}
|
||||
|
||||
private fun emulateConversationChangeListener(conversationInit: Preference?) =
|
||||
OnPreferenceChangeListener { _, newValue ->
|
||||
Preference.OnPreferenceChangeListener { _, newValue ->
|
||||
conversationInit?.isEnabled = newValue as Boolean
|
||||
true
|
||||
}
|
||||
|
||||
private fun connectivityChangeListener() =
|
||||
OnPreferenceChangeListener { _, _ ->
|
||||
context?.network?.scheduleNodeStart()
|
||||
Preference.OnPreferenceChangeListener { _, _ ->
|
||||
activity?.network?.scheduleNodeStart()
|
||||
true
|
||||
}
|
||||
|
||||
// The why-is-it-so-damn-hard-to-group-preferences section
|
||||
override fun getCallbackFragment(): Fragment = this
|
||||
|
||||
override fun onPreferenceStartScreen(
|
||||
preferenceFragmentCompat: PreferenceFragmentCompat,
|
||||
preferenceScreen: PreferenceScreen
|
||||
): Boolean {
|
||||
fragmentManager?.beginTransaction()?.let { ft ->
|
||||
val fragment = SettingsFragment()
|
||||
fragment.arguments = Bundle().apply {
|
||||
putString(PreferenceFragmentCompat.ARG_PREFERENCE_ROOT, preferenceScreen.key)
|
||||
}
|
||||
ft.add(R.id.item_list, fragment, preferenceScreen.key)
|
||||
ft.addToBackStack(preferenceScreen.key)
|
||||
ft.commit()
|
||||
}
|
||||
return true
|
||||
}
|
||||
|
||||
override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
|
||||
super.onViewCreated(view, savedInstanceState)
|
||||
context?.let { ctx -> view.setBackgroundColor(ContextCompat.getColor(ctx, R.color.contentBackground)) }
|
||||
}
|
||||
// FIXME: maybe this is once again necessary, maybe not. Test!
|
||||
// override fun getCallbackFragment(): Fragment = this
|
||||
//
|
||||
// override fun onPreferenceStartScreen(
|
||||
// preferenceFragmentCompat: PreferenceFragment,
|
||||
// preferenceScreen: PreferenceScreen
|
||||
// ): Boolean {
|
||||
// fragmentManager?.beginTransaction()?.let { ft ->
|
||||
// val fragment = SettingsFragment()
|
||||
// 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.commit()
|
||||
// }
|
||||
// return true
|
||||
// }
|
||||
//
|
||||
// override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
|
||||
// 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
|
||||
// Afterthought: here it looks so simple: https://developer.android.com/guide/topics/ui/settings.html
|
||||
// Remind me, why do we need to use PreferenceFragmentCompat?
|
||||
|
@ -17,7 +17,7 @@
|
||||
package ch.dissem.apps.abit
|
||||
|
||||
import android.os.Bundle
|
||||
import android.support.v7.app.AppCompatActivity
|
||||
import androidx.appcompat.app.AppCompatActivity
|
||||
import ch.dissem.apps.abit.service.Singleton
|
||||
import com.mikepenz.materialize.MaterializeBuilder
|
||||
import kotlinx.android.synthetic.main.activity_status.*
|
||||
|
@ -17,7 +17,7 @@
|
||||
package ch.dissem.apps.abit
|
||||
|
||||
import android.os.Bundle
|
||||
import android.support.v4.app.Fragment
|
||||
import androidx.fragment.app.Fragment
|
||||
import android.view.LayoutInflater
|
||||
import android.view.View
|
||||
import android.view.ViewGroup
|
||||
|
@ -16,7 +16,7 @@
|
||||
|
||||
package ch.dissem.apps.abit.adapter
|
||||
|
||||
import android.support.v7.widget.RecyclerView
|
||||
import androidx.recyclerview.widget.RecyclerView
|
||||
import android.view.LayoutInflater
|
||||
import android.view.View
|
||||
import android.view.ViewGroup
|
||||
@ -31,7 +31,7 @@ import java.util.*
|
||||
*/
|
||||
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 {
|
||||
val inflater = LayoutInflater.from(parent.context)
|
||||
@ -63,7 +63,7 @@ class AddressSelectorAdapter(identities: List<BitmessageAddress>) : RecyclerView
|
||||
|
||||
val selected: List<BitmessageAddress>
|
||||
get() {
|
||||
return data
|
||||
return data.asSequence()
|
||||
.filter { it.selected }
|
||||
.mapTo(LinkedList()) { it.data }
|
||||
}
|
||||
|
@ -142,5 +142,4 @@ class ContactAdapter(
|
||||
}
|
||||
}
|
||||
|
||||
fun indexOf(element: BitmessageAddress) = originalData.indexOf(element)
|
||||
}
|
||||
|
@ -1,16 +1,16 @@
|
||||
package ch.dissem.apps.abit.adapter
|
||||
|
||||
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.view.LayoutInflater
|
||||
import android.view.View
|
||||
import android.view.ViewGroup
|
||||
import android.widget.ImageView
|
||||
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.service.Singleton
|
||||
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.valueobject.Label
|
||||
import ch.dissem.bitmessage.ports.MessageRepository
|
||||
import io.reactivex.subjects.BehaviorSubject
|
||||
|
||||
|
||||
class ConversationAdapter internal constructor(
|
||||
ctx: Context,
|
||||
private val parent: Fragment,
|
||||
conversation: Conversation,
|
||||
private val label: Label?
|
||||
label: BehaviorSubject<Label>
|
||||
) : RecyclerView.Adapter<ConversationAdapter.ViewHolder>() {
|
||||
|
||||
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(
|
||||
parent: ViewGroup,
|
||||
@ -98,13 +99,14 @@ class ConversationAdapter internal constructor(
|
||||
val sender = itemView.findViewById<TextView>(R.id.sender)!!
|
||||
val recipient = itemView.findViewById<TextView>(R.id.recipient)!!
|
||||
val status = itemView.findViewById<ImageView>(R.id.status)!!
|
||||
val menu = itemView.findViewById<ImageView>(R.id.menu)!!.also { view ->
|
||||
view.setOnClickListener {
|
||||
val popup = PopupMenu(itemView.context, view)
|
||||
popup.menuInflater.inflate(R.menu.message, popup.menu)
|
||||
popup.setOnMenuItemClickListener {
|
||||
val menu = itemView.findViewById<ImageView>(R.id.menu)!!.apply {
|
||||
setOnClickListener { view ->
|
||||
PopupMenu(itemView.context, view).apply {
|
||||
|
||||
menuInflater.inflate(R.menu.message, menu)
|
||||
setOnMenuItemClickListener { menuItem ->
|
||||
item?.let { item ->
|
||||
when (it.itemId) {
|
||||
when (menuItem.itemId) {
|
||||
R.id.reply -> {
|
||||
ComposeMessageActivity.launchReplyTo(parent, item)
|
||||
true
|
||||
@ -142,7 +144,9 @@ class ConversationAdapter internal constructor(
|
||||
}
|
||||
} ?: false
|
||||
}
|
||||
popup.show()
|
||||
show()
|
||||
|
||||
}
|
||||
}
|
||||
}
|
||||
val text = itemView.findViewById<TextView>(R.id.text)!!.apply {
|
||||
|
@ -2,8 +2,8 @@ package ch.dissem.apps.abit.adapter
|
||||
|
||||
import android.content.Context
|
||||
import android.content.res.ColorStateList
|
||||
import android.support.annotation.ColorInt
|
||||
import android.support.v7.widget.RecyclerView
|
||||
import androidx.annotation.ColorInt
|
||||
import androidx.recyclerview.widget.RecyclerView
|
||||
import android.view.LayoutInflater
|
||||
import android.view.View
|
||||
import android.view.ViewGroup
|
||||
|
@ -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)
|
||||
}
|
@ -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
|
||||
}
|
||||
}
|
||||
}
|
@ -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
|
||||
}
|
||||
}
|
||||
}
|
@ -19,12 +19,12 @@ package ch.dissem.apps.abit.dialog
|
||||
import android.app.AlertDialog
|
||||
import android.content.Context
|
||||
import android.os.Bundle
|
||||
import android.support.v7.app.AppCompatDialogFragment
|
||||
import android.view.LayoutInflater
|
||||
import android.view.View
|
||||
import android.view.ViewGroup
|
||||
import android.widget.TextView
|
||||
import android.widget.Toast
|
||||
import androidx.appcompat.app.AppCompatDialogFragment
|
||||
import ch.dissem.apps.abit.ImportIdentityActivity
|
||||
import ch.dissem.apps.abit.MainActivity
|
||||
import ch.dissem.apps.abit.R
|
||||
@ -33,7 +33,7 @@ import ch.dissem.bitmessage.BitmessageContext
|
||||
import ch.dissem.bitmessage.entity.payload.Pubkey
|
||||
import kotlinx.android.synthetic.main.dialog_add_identity.*
|
||||
import org.jetbrains.anko.doAsync
|
||||
import org.jetbrains.anko.support.v4.startActivity
|
||||
import org.jetbrains.anko.startActivity
|
||||
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_deterministic_address -> DeterministicIdentityDialogFragment().show(fragmentManager, "dialog")
|
||||
else -> return@OnClickListener
|
||||
|
@ -18,7 +18,7 @@ package ch.dissem.apps.abit.dialog
|
||||
|
||||
import android.content.Context
|
||||
import android.os.Bundle
|
||||
import android.support.v7.app.AppCompatDialogFragment
|
||||
import androidx.appcompat.app.AppCompatDialogFragment
|
||||
import android.view.LayoutInflater
|
||||
import android.view.View
|
||||
import android.view.ViewGroup
|
||||
|
@ -19,7 +19,7 @@ package ch.dissem.apps.abit.dialog
|
||||
import android.app.Activity.RESULT_OK
|
||||
import android.content.Intent
|
||||
import android.os.Bundle
|
||||
import android.support.v7.app.AppCompatDialogFragment
|
||||
import androidx.appcompat.app.AppCompatDialogFragment
|
||||
import android.view.LayoutInflater
|
||||
import android.view.View
|
||||
import android.view.ViewGroup
|
||||
|
@ -2,7 +2,7 @@ package ch.dissem.apps.abit.drawer
|
||||
|
||||
import android.content.Context
|
||||
import android.content.Intent
|
||||
import android.support.v4.app.FragmentManager
|
||||
import androidx.fragment.app.FragmentManager
|
||||
import android.view.View
|
||||
import android.widget.Toast
|
||||
import android.widget.Toast.LENGTH_LONG
|
||||
|
@ -21,8 +21,8 @@ import android.app.NotificationChannel
|
||||
import android.app.NotificationManager
|
||||
import android.content.Context
|
||||
import android.os.Build
|
||||
import android.support.annotation.ColorRes
|
||||
import android.support.v4.content.ContextCompat
|
||||
import androidx.annotation.ColorRes
|
||||
import androidx.core.content.ContextCompat
|
||||
import ch.dissem.apps.abit.R
|
||||
import org.jetbrains.anko.notificationManager
|
||||
|
||||
|
@ -17,7 +17,7 @@
|
||||
package ch.dissem.apps.abit.notification
|
||||
|
||||
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.service.Job
|
||||
|
||||
|
@ -17,8 +17,8 @@
|
||||
package ch.dissem.apps.abit.notification
|
||||
|
||||
import android.content.Context
|
||||
import android.support.annotation.StringRes
|
||||
import android.support.v4.app.NotificationCompat
|
||||
import androidx.annotation.StringRes
|
||||
import androidx.core.app.NotificationCompat
|
||||
|
||||
import ch.dissem.apps.abit.R
|
||||
|
||||
|
@ -21,7 +21,7 @@ import android.app.PendingIntent
|
||||
import android.app.PendingIntent.FLAG_UPDATE_CURRENT
|
||||
import android.content.Context
|
||||
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.R
|
||||
import ch.dissem.apps.abit.service.BitmessageIntentService
|
||||
|
@ -21,9 +21,9 @@ import android.app.PendingIntent.FLAG_UPDATE_CURRENT
|
||||
import android.content.Context
|
||||
import android.content.Intent
|
||||
import android.graphics.Typeface
|
||||
import android.support.v4.app.NotificationCompat
|
||||
import android.support.v4.app.NotificationCompat.BigTextStyle
|
||||
import android.support.v4.app.NotificationCompat.InboxStyle
|
||||
import androidx.core.app.NotificationCompat
|
||||
import androidx.core.app.NotificationCompat.BigTextStyle
|
||||
import androidx.core.app.NotificationCompat.InboxStyle
|
||||
import android.text.Spannable
|
||||
import android.text.SpannableString
|
||||
import android.text.Spanned
|
||||
|
@ -19,7 +19,7 @@ package ch.dissem.apps.abit.notification
|
||||
import android.app.PendingIntent
|
||||
import android.content.Context
|
||||
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.R
|
||||
|
@ -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)
|
||||
|
||||
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 (selectIdentityQuery, selectIdentityArgs) = getSelectIdentity(separateIdentities)
|
||||
|
||||
|
@ -3,9 +3,9 @@ package ch.dissem.apps.abit.service
|
||||
import android.app.Service
|
||||
import android.content.Intent
|
||||
import android.os.Binder
|
||||
import android.support.annotation.DrawableRes
|
||||
import android.support.annotation.StringRes
|
||||
import android.support.v4.content.ContextCompat
|
||||
import androidx.annotation.DrawableRes
|
||||
import androidx.annotation.StringRes
|
||||
import androidx.core.content.ContextCompat
|
||||
import ch.dissem.apps.abit.notification.BatchNotification
|
||||
import ch.dissem.apps.abit.notification.BatchNotification.Companion.ONGOING_NOTIFICATION_ID
|
||||
import org.jetbrains.anko.doAsync
|
||||
|
@ -48,6 +48,7 @@ class NodeStartupService : JobService() {
|
||||
addAction(Intent.ACTION_BATTERY_CHANGED)
|
||||
}
|
||||
)
|
||||
startForeground(0, notification.notification)
|
||||
NodeStartupService.running = false
|
||||
|
||||
if (!isRunning) {
|
||||
|
@ -19,7 +19,7 @@ package ch.dissem.apps.abit.service
|
||||
import android.app.Service
|
||||
import android.content.Intent
|
||||
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.Companion.ONGOING_NOTIFICATION_ID
|
||||
import ch.dissem.apps.abit.util.PowStats
|
||||
|
@ -23,19 +23,18 @@ import ch.dissem.apps.abit.R
|
||||
import ch.dissem.apps.abit.adapter.SwipeableMessageAdapter
|
||||
import ch.dissem.apps.abit.listener.MessageListener
|
||||
import ch.dissem.apps.abit.repository.*
|
||||
import ch.dissem.apps.abit.util.Observable
|
||||
import ch.dissem.apps.abit.util.preferences
|
||||
import ch.dissem.bitmessage.BitmessageContext
|
||||
import ch.dissem.bitmessage.cryptography.sc.SpongyCryptography
|
||||
import ch.dissem.bitmessage.entity.BitmessageAddress
|
||||
import ch.dissem.bitmessage.entity.payload.Pubkey
|
||||
import ch.dissem.bitmessage.entity.valueobject.Label
|
||||
import ch.dissem.bitmessage.factory.BufferPool
|
||||
import ch.dissem.bitmessage.networking.nio.NioNetworkHandler
|
||||
import ch.dissem.bitmessage.ports.DefaultLabeler
|
||||
import ch.dissem.bitmessage.utils.ConversationService
|
||||
import ch.dissem.bitmessage.utils.TTL
|
||||
import ch.dissem.bitmessage.utils.UnixTime.DAY
|
||||
import io.reactivex.subjects.BehaviorSubject
|
||||
import org.jetbrains.anko.doAsync
|
||||
import org.jetbrains.anko.uiThread
|
||||
import java.lang.ref.WeakReference
|
||||
@ -44,7 +43,7 @@ import java.lang.ref.WeakReference
|
||||
* Provides singleton objects across the application.
|
||||
*/
|
||||
object Singleton {
|
||||
var currentLabel = Observable<Label?>(null)
|
||||
var currentLabel = BehaviorSubject.create<Label>()
|
||||
|
||||
private var swipeableMessageAdapter: WeakReference<SwipeableMessageAdapter>? = null
|
||||
val labeler = DefaultLabeler().apply {
|
||||
@ -52,7 +51,7 @@ object Singleton {
|
||||
MainActivity.apply {
|
||||
runOnUiThread {
|
||||
swipeableMessageAdapter?.get()?.let { swipeableMessageAdapter ->
|
||||
currentLabel.value?.let { label ->
|
||||
currentLabel.value?.let {label ->
|
||||
when {
|
||||
label.type == Label.Type.TRASH
|
||||
&& added.all { it.type == Label.Type.TRASH }
|
||||
@ -100,7 +99,6 @@ object Singleton {
|
||||
|
||||
fun getBitmessageContext(context: Context): BitmessageContext =
|
||||
init({ bitmessageContext }, { bitmessageContext = it }) {
|
||||
BufferPool.setLimit(4)
|
||||
BitmessageContext.build {
|
||||
TTL.pubkey = 2 * DAY
|
||||
val ctx = context.applicationContext
|
||||
|
@ -1,7 +1,7 @@
|
||||
package ch.dissem.apps.abit.util
|
||||
|
||||
import android.content.Context
|
||||
import android.support.annotation.ColorInt
|
||||
import androidx.annotation.ColorInt
|
||||
import ch.dissem.apps.abit.R
|
||||
import ch.dissem.bitmessage.entity.valueobject.Label
|
||||
import com.mikepenz.community_material_typeface_library.CommunityMaterial
|
||||
|
@ -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)
|
||||
}
|
||||
}
|
@ -57,7 +57,7 @@ class Preferences internal constructor(private val ctx: Context) {
|
||||
ctx.batteryManager.isCharging
|
||||
} else {
|
||||
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
|
||||
}
|
||||
|
||||
|
13
app/src/main/res/drawable/ic_battery_charging.xml
Normal file
13
app/src/main/res/drawable/ic_battery_charging.xml
Normal 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>
|
8
app/src/main/res/drawable/ic_broom.xml
Normal file
8
app/src/main/res/drawable/ic_broom.xml
Normal 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>
|
9
app/src/main/res/drawable/ic_bug_report.xml
Normal file
9
app/src/main/res/drawable/ic_bug_report.xml
Normal 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>
|
8
app/src/main/res/drawable/ic_check_all.xml
Normal file
8
app/src/main/res/drawable/ic_check_all.xml
Normal 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>
|
9
app/src/main/res/drawable/ic_emulate_conversations.xml
Normal file
9
app/src/main/res/drawable/ic_emulate_conversations.xml
Normal 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>
|
9
app/src/main/res/drawable/ic_export.xml
Normal file
9
app/src/main/res/drawable/ic_export.xml
Normal 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>
|
9
app/src/main/res/drawable/ic_import.xml
Normal file
9
app/src/main/res/drawable/ic_import.xml
Normal 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>
|
9
app/src/main/res/drawable/ic_info.xml
Normal file
9
app/src/main/res/drawable/ic_info.xml
Normal 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>
|
13
app/src/main/res/drawable/ic_network_wifi.xml
Normal file
13
app/src/main/res/drawable/ic_network_wifi.xml
Normal 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>
|
9
app/src/main/res/drawable/ic_port.xml
Normal file
9
app/src/main/res/drawable/ic_port.xml
Normal 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>
|
9
app/src/main/res/drawable/ic_separate_identities.xml
Normal file
9
app/src/main/res/drawable/ic_separate_identities.xml
Normal 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>
|
9
app/src/main/res/drawable/ic_support_app.xml
Normal file
9
app/src/main/res/drawable/ic_support_app.xml
Normal 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>
|
@ -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>
|
@ -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:tools="http://schemas.android.com/tools"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="match_parent"
|
||||
android:gravity="center">
|
||||
|
||||
<android.support.v7.widget.Toolbar
|
||||
<androidx.appcompat.widget.Toolbar
|
||||
android:id="@+id/toolbar"
|
||||
android:layout_width="0dp"
|
||||
android:layout_height="64dp"
|
||||
@ -19,7 +19,7 @@
|
||||
tools:ignore="UnusedAttribute"
|
||||
tools:layout_editor_absoluteX="0dp" />
|
||||
|
||||
<android.support.constraint.Guideline
|
||||
<androidx.constraintlayout.widget.Guideline
|
||||
android:id="@+id/guideline"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
@ -74,4 +74,4 @@
|
||||
tools:ignore="UnusedAttribute"
|
||||
tools:layout_editor_absoluteX="8dp" />
|
||||
|
||||
</android.support.constraint.ConstraintLayout>
|
||||
</androidx.constraintlayout.widget.ConstraintLayout>
|
||||
|
@ -4,7 +4,7 @@
|
||||
android:layout_height="wrap_content"
|
||||
android:padding="24dp">
|
||||
|
||||
<android.support.design.widget.TextInputLayout
|
||||
<com.google.android.material.textfield.TextInputLayout
|
||||
android:id="@+id/address_wrapper"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
@ -17,16 +17,17 @@
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:hint="@string/address"
|
||||
android:importantForAutofill="no"
|
||||
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:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_alignStart="@+id/address_wrapper"
|
||||
android:layout_below="@+id/address_wrapper"
|
||||
android:layout_alignStart="@+id/address_wrapper"
|
||||
android:layout_marginTop="16dp">
|
||||
|
||||
<EditText
|
||||
@ -34,18 +35,19 @@
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:hint="@string/label"
|
||||
android:importantForAutofill="no"
|
||||
android:inputType="textPersonName" />
|
||||
|
||||
</android.support.design.widget.TextInputLayout>
|
||||
</com.google.android.material.textfield.TextInputLayout>
|
||||
|
||||
<Switch
|
||||
android:id="@+id/subscribe"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_alignStart="@+id/address_wrapper"
|
||||
android:layout_below="@+id/label_wrapper"
|
||||
android:layout_marginBottom="8dp"
|
||||
android:layout_alignStart="@+id/address_wrapper"
|
||||
android:layout_marginTop="8dp"
|
||||
android:layout_marginBottom="8dp"
|
||||
android:text="@string/subscribe" />
|
||||
|
||||
<Button
|
||||
@ -53,10 +55,10 @@
|
||||
style="?android:attr/borderlessButtonStyle"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_alignParentEnd="true"
|
||||
android:layout_below="@+id/subscribe"
|
||||
android:layout_marginBottom="12dp"
|
||||
android:layout_alignParentEnd="true"
|
||||
android:layout_marginTop="12dp"
|
||||
android:layout_marginBottom="12dp"
|
||||
android:text="@string/do_import" />
|
||||
|
||||
<Button
|
||||
|
@ -5,7 +5,7 @@
|
||||
android:layout_height="match_parent"
|
||||
android:gravity="center">
|
||||
|
||||
<android.support.v7.widget.Toolbar
|
||||
<androidx.appcompat.widget.Toolbar
|
||||
android:id="@+id/toolbar"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="?attr/actionBarSize"
|
||||
|
@ -14,7 +14,7 @@
|
||||
android:textSize="10dp"
|
||||
tools:ignore="SpUsage" />
|
||||
|
||||
<android.support.design.widget.TextInputLayout
|
||||
<com.google.android.material.textfield.TextInputLayout
|
||||
android:id="@+id/label_wrapper"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
@ -27,9 +27,10 @@
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:hint="@string/label"
|
||||
android:importantForAutofill="no"
|
||||
android:inputType="textPersonName" />
|
||||
|
||||
</android.support.design.widget.TextInputLayout>
|
||||
</com.google.android.material.textfield.TextInputLayout>
|
||||
|
||||
<Switch
|
||||
android:id="@+id/subscribe"
|
||||
|
@ -1,5 +1,5 @@
|
||||
<?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:app="http://schemas.android.com/apk/res-auto"
|
||||
xmlns:tools="http://schemas.android.com/tools"
|
||||
@ -19,11 +19,11 @@
|
||||
app:layout_behavior="@string/appbar_scrolling_view_behavior">
|
||||
</TextView>
|
||||
|
||||
<android.support.design.widget.AppBarLayout
|
||||
<com.google.android.material.appbar.AppBarLayout
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content">
|
||||
|
||||
<android.support.v7.widget.Toolbar
|
||||
<androidx.appcompat.widget.Toolbar
|
||||
android:id="@+id/toolbar"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="?attr/actionBarSize"
|
||||
@ -36,6 +36,6 @@
|
||||
app:popupTheme="@style/ThemeOverlay.AppCompat.Light"
|
||||
tools:ignore="UnusedAttribute"/>
|
||||
|
||||
</android.support.design.widget.AppBarLayout>
|
||||
</com.google.android.material.appbar.AppBarLayout>
|
||||
|
||||
</android.support.design.widget.CoordinatorLayout>
|
||||
</androidx.coordinatorlayout.widget.CoordinatorLayout>
|
||||
|
@ -14,15 +14,15 @@
|
||||
~ 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:tools="http://schemas.android.com/tools"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="match_parent"
|
||||
android:paddingBottom="18dp"
|
||||
android:paddingEnd="24dp"
|
||||
android:paddingStart="24dp"
|
||||
android:paddingTop="18dp">
|
||||
android:paddingTop="18dp"
|
||||
android:paddingEnd="24dp"
|
||||
android:paddingBottom="18dp">
|
||||
|
||||
<TextView
|
||||
android:id="@+id/description"
|
||||
@ -34,7 +34,7 @@
|
||||
tools:layout_constraintLeft_creator="1"
|
||||
tools:layout_constraintTop_creator="1" />
|
||||
|
||||
<android.support.design.widget.TextInputLayout
|
||||
<com.google.android.material.textfield.TextInputLayout
|
||||
android:id="@+id/label_wrapper"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
@ -47,11 +47,12 @@
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:hint="@string/label"
|
||||
android:autofillHints="label"
|
||||
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:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
@ -63,11 +64,12 @@
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:hint="@string/passphrase"
|
||||
android:autofillHints="passphrase"
|
||||
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:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
@ -80,11 +82,12 @@
|
||||
android:layout_height="wrap_content"
|
||||
android:ems="10"
|
||||
android:hint="@string/number_of_identities"
|
||||
android:autofillHints="numberOfIdentities"
|
||||
android:inputType="number"
|
||||
android:text="1"
|
||||
tools:ignore="HardcodedText" />
|
||||
|
||||
</android.support.design.widget.TextInputLayout>
|
||||
</com.google.android.material.textfield.TextInputLayout>
|
||||
|
||||
<Switch
|
||||
android:id="@+id/shorter"
|
||||
@ -115,4 +118,4 @@
|
||||
app:layout_constraintBottom_toBottomOf="@id/ok"
|
||||
app:layout_constraintRight_toLeftOf="@id/ok" />
|
||||
|
||||
</android.support.constraint.ConstraintLayout>
|
||||
</androidx.constraintlayout.widget.ConstraintLayout>
|
||||
|
@ -15,7 +15,7 @@
|
||||
~ limitations under the License.
|
||||
-->
|
||||
|
||||
<android.support.constraint.ConstraintLayout
|
||||
<androidx.constraintlayout.widget.ConstraintLayout
|
||||
xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
xmlns:app="http://schemas.android.com/apk/res-auto"
|
||||
xmlns:tools="http://schemas.android.com/tools"
|
||||
@ -98,4 +98,4 @@
|
||||
android:textColor="@color/colorAccent"
|
||||
app:layout_constraintRight_toLeftOf="@+id/ok"
|
||||
app:layout_constraintTop_toBottomOf="@+id/radioGroup"/>
|
||||
</android.support.constraint.ConstraintLayout>
|
||||
</androidx.constraintlayout.widget.ConstraintLayout>
|
||||
|
@ -15,7 +15,7 @@
|
||||
~ limitations under the License.
|
||||
-->
|
||||
|
||||
<android.support.constraint.ConstraintLayout
|
||||
<androidx.constraintlayout.widget.ConstraintLayout
|
||||
xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
xmlns:app="http://schemas.android.com/apk/res-auto"
|
||||
xmlns:tools="http://schemas.android.com/tools"
|
||||
@ -56,4 +56,4 @@
|
||||
app:layout_constraintEnd_toEndOf="@id/description"
|
||||
app:layout_constraintTop_toBottomOf="@+id/ok"
|
||||
tools:layout_editor_absoluteX="8dp"/>
|
||||
</android.support.constraint.ConstraintLayout>
|
||||
</androidx.constraintlayout.widget.ConstraintLayout>
|
||||
|
@ -14,5 +14,6 @@
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_gravity="center_horizontal"
|
||||
android:hint="@string/passphrase"
|
||||
android:autofillHints="passphrase"
|
||||
android:inputType="textMultiLine"/>
|
||||
</LinearLayout>
|
||||
|
@ -1,5 +1,4 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<!--
|
||||
<?xml version="1.0" encoding="utf-8"?><!--
|
||||
~ Copyright 2015 Christian Basler
|
||||
~
|
||||
~ Licensed under the Apache License, Version 2.0 (the "License");
|
||||
@ -28,19 +27,20 @@
|
||||
android:layout_alignParentTop="true"
|
||||
android:layout_margin="16dp"
|
||||
android:src="@color/colorAccent"
|
||||
tools:ignore="ContentDescription"/>
|
||||
tools:ignore="ContentDescription" />
|
||||
|
||||
<EditText
|
||||
android:id="@+id/name"
|
||||
android:layout_width="0dp"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_alignParentEnd="true"
|
||||
android:layout_alignTop="@+id/avatar"
|
||||
android:layout_alignParentEnd="true"
|
||||
android:layout_marginEnd="16dp"
|
||||
android:layout_toEndOf="@+id/avatar"
|
||||
android:importantForAutofill="no"
|
||||
android:inputType="textPersonName"
|
||||
android:text=""
|
||||
tools:ignore="LabelFor"/>
|
||||
tools:ignore="LabelFor" />
|
||||
|
||||
<TextView
|
||||
android:id="@+id/address"
|
||||
@ -52,7 +52,7 @@
|
||||
android:paddingRight="16dp"
|
||||
android:textAppearance="?android:attr/textAppearanceSmall"
|
||||
android:textStyle="bold"
|
||||
tools:text="BM-XyYxXyYxXyYxXyYxXyYx"/>
|
||||
tools:text="BM-XyYxXyYxXyYxXyYxXyYx" />
|
||||
|
||||
<TextView
|
||||
android:id="@+id/stream_number"
|
||||
@ -64,7 +64,7 @@
|
||||
android:paddingLeft="16dp"
|
||||
android:paddingRight="16dp"
|
||||
android:textAppearance="?android:attr/textAppearanceSmall"
|
||||
tools:text="Stream #"/>
|
||||
tools:text="Stream #" />
|
||||
|
||||
<Switch
|
||||
android:id="@+id/active"
|
||||
@ -72,21 +72,21 @@
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_below="@+id/stream_number"
|
||||
android:paddingLeft="16dp"
|
||||
android:paddingRight="16dp"
|
||||
android:paddingTop="16dp"
|
||||
android:text="@string/subscribed"/>
|
||||
android:paddingRight="16dp"
|
||||
android:text="@string/subscribed" />
|
||||
|
||||
<ImageView
|
||||
android:id="@+id/pubkey_available"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_alignParentStart="true"
|
||||
android:layout_below="@+id/active"
|
||||
android:paddingEnd="4dp"
|
||||
android:layout_alignParentStart="true"
|
||||
android:paddingStart="16dp"
|
||||
android:paddingTop="16dp"
|
||||
android:paddingEnd="4dp"
|
||||
android:src="@drawable/public_key"
|
||||
tools:ignore="ContentDescription"/>
|
||||
tools:ignore="ContentDescription" />
|
||||
|
||||
<TextView
|
||||
android:id="@+id/pubkey_available_desc"
|
||||
@ -95,25 +95,25 @@
|
||||
android:layout_alignBottom="@id/pubkey_available"
|
||||
android:layout_alignParentEnd="true"
|
||||
android:layout_toEndOf="@id/pubkey_available"
|
||||
android:paddingEnd="16dp"
|
||||
android:paddingStart="0dp"
|
||||
android:paddingEnd="16dp"
|
||||
android:text="@string/pubkey_available"
|
||||
android:textAppearance="?android:attr/textAppearanceSmall"/>
|
||||
android:textAppearance="?android:attr/textAppearanceSmall" />
|
||||
|
||||
<ImageView
|
||||
android:id="@+id/qr_code"
|
||||
android:layout_width="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_marginBottom="64dp"
|
||||
android:layout_marginEnd="16dp"
|
||||
android:layout_alignParentStart="true"
|
||||
android:layout_alignParentEnd="true"
|
||||
android:layout_alignParentBottom="true"
|
||||
android:layout_marginStart="16dp"
|
||||
android:layout_marginTop="24dp"
|
||||
android:layout_marginEnd="16dp"
|
||||
android:layout_marginBottom="64dp"
|
||||
android:contentDescription="@string/alt_qr_code"
|
||||
android:elevation="2dp"
|
||||
tools:ignore="UnusedAttribute"
|
||||
tools:src="@drawable/public_key"/>
|
||||
tools:src="@drawable/public_key" />
|
||||
</RelativeLayout>
|
||||
|
@ -4,7 +4,7 @@
|
||||
android:layout_height="match_parent">
|
||||
|
||||
<ListView
|
||||
android:id="@id/android:list"
|
||||
android:id="@android:id/list"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_alignParentBottom="true"
|
||||
|
@ -24,7 +24,7 @@
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content" />
|
||||
|
||||
<android.support.design.widget.TextInputLayout
|
||||
<com.google.android.material.textfield.TextInputLayout
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:paddingTop="4dp">
|
||||
@ -33,13 +33,14 @@
|
||||
android:id="@+id/recipient_input"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:autofillHints="bitmessageAddress"
|
||||
android:hint="@string/to"
|
||||
android:inputType="textNoSuggestions"
|
||||
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_height="wrap_content">
|
||||
|
||||
@ -47,17 +48,19 @@
|
||||
android:id="@+id/subject_input"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:autofillHints="subject"
|
||||
android:hint="@string/subject"
|
||||
android:inputType="textEmailSubject"
|
||||
android:textAppearance="?android:attr/textAppearanceLarge" />
|
||||
|
||||
</android.support.design.widget.TextInputLayout>
|
||||
</com.google.android.material.textfield.TextInputLayout>
|
||||
|
||||
<EditText
|
||||
android:id="@+id/body_input"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_weight="1"
|
||||
android:autofillHints="body, message"
|
||||
android:gravity="start|top"
|
||||
android:hint="@string/compose_body_hint"
|
||||
android:inputType="textMultiLine|textCapSentences"
|
||||
|
@ -41,7 +41,7 @@
|
||||
android:layout_below="@id/subject"
|
||||
android:background="@color/divider" />
|
||||
|
||||
<android.support.v7.widget.RecyclerView
|
||||
<androidx.recyclerview.widget.RecyclerView
|
||||
android:id="@+id/messages"
|
||||
android:layout_width="fill_parent"
|
||||
android:layout_height="wrap_content"
|
||||
|
@ -15,7 +15,7 @@
|
||||
~ limitations under the License.
|
||||
-->
|
||||
|
||||
<android.support.constraint.ConstraintLayout
|
||||
<androidx.constraintlayout.widget.ConstraintLayout
|
||||
xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
xmlns:app="http://schemas.android.com/apk/res-auto"
|
||||
android:layout_width="match_parent"
|
||||
@ -41,6 +41,7 @@
|
||||
android:gravity="start|top"
|
||||
android:hint="@string/wif_string"
|
||||
android:inputType="textMultiLine|text"
|
||||
android:autofillHints="wif, comment, data"
|
||||
app:layout_constraintBottom_toTopOf="@+id/next"
|
||||
app:layout_constraintEnd_toEndOf="parent"
|
||||
app:layout_constraintStart_toStartOf="parent"
|
||||
@ -57,4 +58,4 @@
|
||||
app:layout_constraintBottom_toBottomOf="parent"
|
||||
app:layout_constraintRight_toRightOf="parent"/>
|
||||
|
||||
</android.support.constraint.ConstraintLayout>
|
||||
</androidx.constraintlayout.widget.ConstraintLayout>
|
||||
|
@ -15,7 +15,7 @@
|
||||
~ limitations under the License.
|
||||
-->
|
||||
|
||||
<android.support.constraint.ConstraintLayout
|
||||
<androidx.constraintlayout.widget.ConstraintLayout
|
||||
xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
xmlns:app="http://schemas.android.com/apk/res-auto"
|
||||
android:layout_width="match_parent"
|
||||
@ -33,7 +33,7 @@
|
||||
app:layout_constraintLeft_toLeftOf="parent"
|
||||
app:layout_constraintTop_toTopOf="parent"/>
|
||||
|
||||
<android.support.v7.widget.RecyclerView
|
||||
<androidx.recyclerview.widget.RecyclerView
|
||||
android:id="@+id/recycler_view"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="0dp"
|
||||
@ -55,4 +55,4 @@
|
||||
app:layout_constraintBottom_toBottomOf="parent"
|
||||
app:layout_constraintRight_toRightOf="parent"/>
|
||||
|
||||
</android.support.constraint.ConstraintLayout>
|
||||
</androidx.constraintlayout.widget.ConstraintLayout>
|
||||
|
@ -78,7 +78,7 @@
|
||||
android:paddingRight="8dp"
|
||||
tools:text="Recipient" />
|
||||
|
||||
<android.support.v7.widget.RecyclerView
|
||||
<androidx.recyclerview.widget.RecyclerView
|
||||
android:id="@+id/parents"
|
||||
android:layout_width="fill_parent"
|
||||
android:layout_height="wrap_content"
|
||||
@ -99,7 +99,7 @@
|
||||
tools:text="Message Body"
|
||||
android:textIsSelectable="true" />
|
||||
|
||||
<android.support.v7.widget.RecyclerView
|
||||
<androidx.recyclerview.widget.RecyclerView
|
||||
android:id="@+id/labels"
|
||||
android:layout_width="fill_parent"
|
||||
android:layout_height="wrap_content"
|
||||
@ -108,7 +108,7 @@
|
||||
android:layout_marginRight="16dp"
|
||||
android:layout_marginBottom="16dp"/>
|
||||
|
||||
<android.support.v7.widget.RecyclerView
|
||||
<androidx.recyclerview.widget.RecyclerView
|
||||
android:id="@+id/responses"
|
||||
android:layout_width="fill_parent"
|
||||
android:layout_height="wrap_content"
|
||||
|
@ -4,7 +4,7 @@
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="match_parent">
|
||||
|
||||
<android.support.v7.widget.RecyclerView
|
||||
<androidx.recyclerview.widget.RecyclerView
|
||||
android:id="@+id/recycler_view"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="0dp"
|
||||
|
@ -88,7 +88,7 @@
|
||||
android:textIsSelectable="true"
|
||||
tools:text="Message Body" />
|
||||
|
||||
<android.support.v7.widget.RecyclerView
|
||||
<androidx.recyclerview.widget.RecyclerView
|
||||
android:id="@+id/labels"
|
||||
android:layout_width="fill_parent"
|
||||
android:layout_height="wrap_content"
|
||||
|
@ -1,5 +1,5 @@
|
||||
<?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:tools="http://schemas.android.com/tools"
|
||||
android:layout_width="match_parent"
|
||||
@ -16,11 +16,11 @@
|
||||
tools:context=".ComposeMessageActivity"
|
||||
tools:layout="@layout/fragment_compose_message"/>
|
||||
|
||||
<android.support.design.widget.AppBarLayout
|
||||
<com.google.android.material.appbar.AppBarLayout
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content">
|
||||
|
||||
<android.support.v7.widget.Toolbar
|
||||
<androidx.appcompat.widget.Toolbar
|
||||
android:id="@+id/toolbar"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="?attr/actionBarSize"
|
||||
@ -30,7 +30,7 @@
|
||||
app:popupTheme="@style/ThemeOverlay.AppCompat.Light"
|
||||
tools:ignore="UnusedAttribute"/>
|
||||
|
||||
</android.support.design.widget.AppBarLayout>
|
||||
</com.google.android.material.appbar.AppBarLayout>
|
||||
|
||||
</android.support.design.widget.CoordinatorLayout>
|
||||
</androidx.coordinatorlayout.widget.CoordinatorLayout>
|
||||
|
||||
|
@ -1,5 +1,5 @@
|
||||
<?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:tools="http://schemas.android.com/tools"
|
||||
android:layout_width="match_parent"
|
||||
@ -16,11 +16,11 @@
|
||||
tools:context=".ComposeMessageActivity"
|
||||
tools:layout="@layout/fragment_compose_message"/>
|
||||
|
||||
<android.support.design.widget.AppBarLayout
|
||||
<com.google.android.material.appbar.AppBarLayout
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content">
|
||||
|
||||
<android.support.v7.widget.Toolbar
|
||||
<androidx.appcompat.widget.Toolbar
|
||||
android:id="@+id/toolbar"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="?attr/actionBarSize"
|
||||
@ -31,7 +31,7 @@
|
||||
app:popupTheme="@style/ThemeOverlay.AppCompat.Light"
|
||||
tools:ignore="UnusedAttribute"/>
|
||||
|
||||
</android.support.design.widget.AppBarLayout>
|
||||
</com.google.android.material.appbar.AppBarLayout>
|
||||
|
||||
</android.support.design.widget.CoordinatorLayout>
|
||||
</androidx.coordinatorlayout.widget.CoordinatorLayout>
|
||||
|
||||
|
@ -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="preference_group_advanced">Erweitert</string>
|
||||
<string name="preference_group_network_and_performance">Netzwerk & 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_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="preference_port">Port</string>
|
||||
</resources>
|
||||
|
@ -37,10 +37,6 @@
|
||||
<string name="archive">Archive</string>
|
||||
<string name="empty_trash">Empty Trash</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="full_node">Full node</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_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="error_invalid_sync_port">Invalid port in synchronization settings: %s</string>
|
||||
<string name="compose_body_hint">Write message</string>
|
||||
<string name="contacts_and_subscriptions">Contacts</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="about">About Abit</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_batch">Grouping existing messages by subject</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 & 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_summary"></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_summary">Only connect when device is plugged in</string>
|
||||
<string name="unknown">Unknown</string>
|
||||
|
@ -1,92 +1,94 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<PreferenceScreen xmlns:android="http://schemas.android.com/apk/res/android">
|
||||
|
||||
<PreferenceScreen
|
||||
android:key="preference_ux"
|
||||
android:persistent="false"
|
||||
android:summary="@string/preference_group_user_experience_summary"
|
||||
android:title="@string/preference_group_user_experience">
|
||||
<PreferenceCategory android:title="@string/preference_group_user_experience">
|
||||
|
||||
<SwitchPreferenceCompat
|
||||
android:defaultValue="false"
|
||||
android:icon="@drawable/ic_separate_identities"
|
||||
android:key="separate_identities"
|
||||
android:summary="@string/preference_separate_identities_summary"
|
||||
android:title="@string/preference_separate_identities" />
|
||||
<SwitchPreferenceCompat
|
||||
android:defaultValue="true"
|
||||
android:icon="@drawable/ic_emulate_conversations"
|
||||
android:key="emulate_conversations"
|
||||
android:summary="@string/emulate_conversations_summary"
|
||||
android:title="@string/emulate_conversations" />
|
||||
<Preference
|
||||
android:defaultValue="true"
|
||||
android:icon="@drawable/ic_emulate_conversations"
|
||||
android:key="emulate_conversations_initialize"
|
||||
android:summary="@string/emulate_conversations_summary"
|
||||
android:title="@string/emulate_conversations_initialize" />
|
||||
|
||||
</PreferenceScreen>
|
||||
</PreferenceCategory>
|
||||
|
||||
<PreferenceScreen
|
||||
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">
|
||||
<PreferenceCategory android:title="@string/preference_group_network_and_performance">
|
||||
|
||||
<SwitchPreferenceCompat
|
||||
android:defaultValue="true"
|
||||
android:icon="@drawable/ic_network_wifi"
|
||||
android:key="wifi_only"
|
||||
android:summary="@string/wifi_only_summary"
|
||||
android:title="@string/wifi_only" />
|
||||
<SwitchPreferenceCompat
|
||||
android:defaultValue="false"
|
||||
android:icon="@drawable/ic_battery_charging"
|
||||
android:key="require_charging"
|
||||
android:summary="@string/require_charging_summary"
|
||||
android:title="@string/require_charging" />
|
||||
<SwitchPreferenceCompat
|
||||
android:defaultValue="true"
|
||||
android:icon="@drawable/ic_check_all"
|
||||
android:key="request_acknowledgements"
|
||||
android:summary="@string/request_acknowledgements_summary"
|
||||
android:title="@string/request_acknowledgements" />
|
||||
|
||||
</PreferenceScreen>
|
||||
</PreferenceCategory>
|
||||
|
||||
<PreferenceScreen
|
||||
android:key="preference_advanced"
|
||||
android:persistent="false"
|
||||
android:summary="@string/preference_group_advanced_summary"
|
||||
android:title="@string/preference_group_advanced">
|
||||
<PreferenceCategory android:title="@string/preference_group_advanced">
|
||||
|
||||
<Preference
|
||||
android:icon="@drawable/ic_broom"
|
||||
android:key="cleanup"
|
||||
android:summary="@string/cleanup_summary"
|
||||
android:title="@string/cleanup" />
|
||||
<Preference
|
||||
android:icon="@drawable/ic_export"
|
||||
android:key="export"
|
||||
android:summary="@string/export_data_summary"
|
||||
android:title="@string/export_data" />
|
||||
<Preference
|
||||
android:icon="@drawable/ic_import"
|
||||
android:key="import"
|
||||
android:summary="@string/import_data_summary"
|
||||
android:title="@string/import_data" />
|
||||
|
||||
<Preference
|
||||
android:icon="@drawable/ic_bug_report"
|
||||
android:key="status"
|
||||
android:summary="@string/status_summary"
|
||||
android:title="@string/status" />
|
||||
|
||||
<EditTextPreference
|
||||
android:defaultValue="8444"
|
||||
android:icon="@drawable/ic_port"
|
||||
android:key="listening_port"
|
||||
android:numeric="integer"
|
||||
android:summary="@string/preference_port_summary"
|
||||
android:title="@string/preference_port"
|
||||
android:numeric="integer"/>
|
||||
android:title="@string/preference_port" />
|
||||
|
||||
</PreferenceScreen>
|
||||
</PreferenceCategory>
|
||||
|
||||
<PreferenceCategory android:title="@string/preference_group_app">
|
||||
<Preference
|
||||
android:icon="@drawable/ic_info"
|
||||
android:key="about"
|
||||
android:summary="@string/about_summary"
|
||||
android:title="@string/about" />
|
||||
<Preference
|
||||
android:icon="@drawable/ic_support_app"
|
||||
android:key="help_out"
|
||||
android:summary="@string/help_out_summary"
|
||||
android:title="@string/help_out">
|
||||
@ -94,4 +96,5 @@
|
||||
android:action="android.intent.action.VIEW"
|
||||
android:data="@string/help_out_link" />
|
||||
</Preference>
|
||||
</PreferenceCategory>
|
||||
</PreferenceScreen>
|
||||
|
@ -21,6 +21,7 @@ import ch.dissem.apps.abit.repository.AndroidAddressRepository
|
||||
import ch.dissem.apps.abit.repository.AndroidLabelRepository
|
||||
import ch.dissem.apps.abit.repository.AndroidMessageRepository
|
||||
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.entity.BitmessageAddress
|
||||
import ch.dissem.bitmessage.entity.ObjectMessage
|
||||
@ -67,7 +68,7 @@ class AndroidMessageRepositoryTest : TestBase() {
|
||||
|
||||
val addressRepo = AndroidAddressRepository(sqlHelper)
|
||||
val labelRepo = AndroidLabelRepository(sqlHelper, RuntimeEnvironment.application)
|
||||
repo = AndroidMessageRepository(sqlHelper)
|
||||
repo = AndroidMessageRepository(sqlHelper, RuntimeEnvironment.application.preferences)
|
||||
mockedInternalContext(
|
||||
cryptography = BouncyCryptography(),
|
||||
addressRepository = addressRepo,
|
||||
|
@ -18,6 +18,7 @@ package ch.dissem.bitmessage.repository
|
||||
|
||||
import android.os.Build.VERSION_CODES.LOLLIPOP
|
||||
import ch.dissem.apps.abit.repository.*
|
||||
import ch.dissem.apps.abit.util.preferences
|
||||
import ch.dissem.bitmessage.entity.BitmessageAddress
|
||||
import ch.dissem.bitmessage.entity.ObjectMessage
|
||||
import ch.dissem.bitmessage.entity.Plaintext
|
||||
@ -60,7 +61,7 @@ class AndroidProofOfWorkRepositoryTest : TestBase() {
|
||||
RuntimeEnvironment.application.deleteDatabase(SqlHelper.DATABASE_NAME)
|
||||
val sqlHelper = SqlHelper(RuntimeEnvironment.application)
|
||||
addressRepo = AndroidAddressRepository(sqlHelper)
|
||||
messageRepo = AndroidMessageRepository(sqlHelper)
|
||||
messageRepo = AndroidMessageRepository(sqlHelper, RuntimeEnvironment.application.preferences)
|
||||
repo = AndroidProofOfWorkRepository(sqlHelper)
|
||||
mockedInternalContext(
|
||||
addressRepository = addressRepo,
|
||||
|
@ -1,12 +1,12 @@
|
||||
buildscript {
|
||||
ext.kotlin_version = '1.2.51'
|
||||
ext.kotlin_version = '1.2.71'
|
||||
ext.anko_version = '0.10.5'
|
||||
repositories {
|
||||
jcenter()
|
||||
google()
|
||||
jcenter()
|
||||
}
|
||||
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 'com.github.ben-manes:gradle-versions-plugin:0.20.0'
|
||||
|
||||
@ -21,7 +21,6 @@ allprojects {
|
||||
repositories {
|
||||
google()
|
||||
jcenter()
|
||||
mavenCentral()
|
||||
maven { url 'https://oss.sonatype.org/content/repositories/snapshots/' }
|
||||
maven { url "https://jitpack.io" }
|
||||
}
|
||||
|
@ -10,6 +10,8 @@
|
||||
# Specifies the JVM arguments used for the daemon process.
|
||||
# The setting is particularly useful for tweaking memory settings.
|
||||
# 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
|
||||
|
||||
# When configured, Gradle will run in incubating parallel mode.
|
||||
|
4
gradle/wrapper/gradle-wrapper.properties
vendored
4
gradle/wrapper/gradle-wrapper.properties
vendored
@ -1,6 +1,6 @@
|
||||
#Sat Mar 03 14:35:52 CET 2018
|
||||
#Tue Aug 28 16:14:32 CEST 2018
|
||||
distributionBase=GRADLE_USER_HOME
|
||||
distributionPath=wrapper/dists
|
||||
zipStoreBase=GRADLE_USER_HOME
|
||||
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
|
||||
|
Loading…
Reference in New Issue
Block a user