Use observer pattern for label change
This commit is contained in:
parent
4c89bfe1cf
commit
df581f4c51
@ -17,7 +17,7 @@ android {
|
|||||||
buildToolsVersion "26.0.2"
|
buildToolsVersion "26.0.2"
|
||||||
|
|
||||||
defaultConfig {
|
defaultConfig {
|
||||||
applicationId "ch.dissem.apps." + appName.toLowerCase()
|
applicationId "ch.dissem.apps.${appName.toLowerCase()}"
|
||||||
minSdkVersion 19
|
minSdkVersion 19
|
||||||
targetSdkVersion 27
|
targetSdkVersion 27
|
||||||
versionCode 17
|
versionCode 17
|
||||||
|
@ -127,8 +127,6 @@ abstract class AbstractItemListFragment<L, T> : ListFragment(), ListHolder<L> {
|
|||||||
activatedPosition = position
|
activatedPosition = position
|
||||||
}
|
}
|
||||||
|
|
||||||
override var currentLabel: L? = null
|
|
||||||
|
|
||||||
override fun showPreviousList() = false
|
override fun showPreviousList() = false
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -24,7 +24,5 @@ interface ListHolder<L> {
|
|||||||
|
|
||||||
fun setActivateOnItemClick(activateOnItemClick: Boolean)
|
fun setActivateOnItemClick(activateOnItemClick: Boolean)
|
||||||
|
|
||||||
var currentLabel: L?
|
|
||||||
|
|
||||||
fun showPreviousList(): Boolean
|
fun showPreviousList(): Boolean
|
||||||
}
|
}
|
||||||
|
@ -30,6 +30,7 @@ import ch.dissem.apps.abit.drawer.ProfileSelectionListener
|
|||||||
import ch.dissem.apps.abit.listener.ListSelectionListener
|
import ch.dissem.apps.abit.listener.ListSelectionListener
|
||||||
import ch.dissem.apps.abit.repository.AndroidLabelRepository.Companion.LABEL_ARCHIVE
|
import ch.dissem.apps.abit.repository.AndroidLabelRepository.Companion.LABEL_ARCHIVE
|
||||||
import ch.dissem.apps.abit.service.Singleton
|
import ch.dissem.apps.abit.service.Singleton
|
||||||
|
import ch.dissem.apps.abit.service.Singleton.currentLabel
|
||||||
import ch.dissem.apps.abit.synchronization.SyncAdapter
|
import ch.dissem.apps.abit.synchronization.SyncAdapter
|
||||||
import ch.dissem.apps.abit.util.Labels
|
import ch.dissem.apps.abit.util.Labels
|
||||||
import ch.dissem.apps.abit.util.NetworkUtils
|
import ch.dissem.apps.abit.util.NetworkUtils
|
||||||
@ -89,9 +90,6 @@ class MainActivity : AppCompatActivity(), ListSelectionListener<Serializable> {
|
|||||||
var hasDetailPane: Boolean = false
|
var hasDetailPane: Boolean = false
|
||||||
private set
|
private set
|
||||||
|
|
||||||
var selectedLabel: Label? = null
|
|
||||||
private set
|
|
||||||
|
|
||||||
private lateinit var bmc: BitmessageContext
|
private lateinit var bmc: BitmessageContext
|
||||||
private lateinit var accountHeader: AccountHeader
|
private lateinit var accountHeader: AccountHeader
|
||||||
|
|
||||||
@ -280,14 +278,16 @@ class MainActivity : AppCompatActivity(), ListSelectionListener<Serializable> {
|
|||||||
|
|
||||||
uiThread {
|
uiThread {
|
||||||
if (intent.hasExtra(EXTRA_SHOW_LABEL)) {
|
if (intent.hasExtra(EXTRA_SHOW_LABEL)) {
|
||||||
selectedLabel = intent.getSerializableExtra(EXTRA_SHOW_LABEL) as Label
|
currentLabel.value = intent.getSerializableExtra(EXTRA_SHOW_LABEL) as Label
|
||||||
} else if (selectedLabel == null) {
|
} else if (currentLabel.value == null) {
|
||||||
selectedLabel = labels[0]
|
currentLabel.value = labels[0]
|
||||||
}
|
}
|
||||||
for (label in labels) {
|
for (label in labels) {
|
||||||
addLabelEntry(label)
|
addLabelEntry(label)
|
||||||
}
|
}
|
||||||
drawer.setSelection(selectedLabel?.id as Long)
|
currentLabel.value?.let {
|
||||||
|
drawer.setSelection(it.id as Long)
|
||||||
|
}
|
||||||
updateUnread()
|
updateUnread()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -295,30 +295,19 @@ class MainActivity : AppCompatActivity(), ListSelectionListener<Serializable> {
|
|||||||
|
|
||||||
override fun onBackPressed() {
|
override fun onBackPressed() {
|
||||||
val listFragment = supportFragmentManager.findFragmentById(R.id.item_list)
|
val listFragment = supportFragmentManager.findFragmentById(R.id.item_list)
|
||||||
if (listFragment is ListHolder<*>) {
|
if (listFragment !is ListHolder<*> || !listFragment.showPreviousList()) {
|
||||||
val listHolder = listFragment as ListHolder<*>
|
|
||||||
if (listHolder.showPreviousList()) {
|
|
||||||
drawer.getDrawerItem(listHolder.currentLabel)?.let {
|
|
||||||
drawer.setSelection(it)
|
|
||||||
}
|
|
||||||
return
|
|
||||||
}
|
|
||||||
}
|
|
||||||
super.onBackPressed()
|
super.onBackPressed()
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
private inner class DrawerItemClickListener : Drawer.OnDrawerItemClickListener {
|
private inner class DrawerItemClickListener : Drawer.OnDrawerItemClickListener {
|
||||||
override fun onItemClick(view: View?, position: Int, item: IDrawerItem<*, *>): Boolean {
|
override fun onItemClick(view: View?, position: Int, item: IDrawerItem<*, *>): Boolean {
|
||||||
val itemList = supportFragmentManager.findFragmentById(R.id.item_list)
|
val itemList = supportFragmentManager.findFragmentById(R.id.item_list)
|
||||||
val tag = item.tag
|
val tag = item.tag
|
||||||
if (tag is Label) {
|
if (tag is Label) {
|
||||||
selectedLabel = tag
|
currentLabel.value = tag
|
||||||
if (itemList is MessageListFragment) {
|
if (itemList !is MessageListFragment) {
|
||||||
itemList.updateList(tag)
|
changeList(MessageListFragment())
|
||||||
} else {
|
|
||||||
val listFragment = MessageListFragment()
|
|
||||||
changeList(listFragment)
|
|
||||||
listFragment.updateList(tag)
|
|
||||||
}
|
}
|
||||||
return false
|
return false
|
||||||
} else if (item is Nameable<*>) {
|
} else if (item is Nameable<*>) {
|
||||||
@ -347,33 +336,23 @@ class MainActivity : AppCompatActivity(), ListSelectionListener<Serializable> {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun onSaveInstanceState(savedInstanceState: Bundle) {
|
|
||||||
super.onSaveInstanceState(savedInstanceState)
|
|
||||||
savedInstanceState.putSerializable("selectedLabel", selectedLabel)
|
|
||||||
}
|
|
||||||
|
|
||||||
override fun onRestoreInstanceState(savedInstanceState: Bundle) {
|
|
||||||
selectedLabel = savedInstanceState.getSerializable("selectedLabel") as? Label
|
|
||||||
|
|
||||||
selectedLabel?.let { selectedLabel ->
|
|
||||||
drawer.getDrawerItem(selectedLabel)?.let { selectedItem ->
|
|
||||||
drawer.setSelection(selectedItem)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
super.onRestoreInstanceState(savedInstanceState)
|
|
||||||
}
|
|
||||||
|
|
||||||
override fun onResume() {
|
override fun onResume() {
|
||||||
updateUnread()
|
updateUnread()
|
||||||
if (Preferences.isFullNodeActive(this) && Preferences.isConnectionAllowed(this@MainActivity)) {
|
if (Preferences.isFullNodeActive(this) && Preferences.isConnectionAllowed(this@MainActivity)) {
|
||||||
NetworkUtils.enableNode(this, false)
|
NetworkUtils.enableNode(this, false)
|
||||||
}
|
}
|
||||||
Singleton.getMessageListener(this).resetNotification()
|
Singleton.getMessageListener(this).resetNotification()
|
||||||
|
currentLabel.addObserver(this) { label ->
|
||||||
|
if (label != null) {
|
||||||
|
drawer.setSelection(label.id as Long)
|
||||||
|
}
|
||||||
|
}
|
||||||
active = true
|
active = true
|
||||||
super.onResume()
|
super.onResume()
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun onPause() {
|
override fun onPause() {
|
||||||
|
currentLabel.removeObserver(this)
|
||||||
super.onPause()
|
super.onPause()
|
||||||
active = false
|
active = false
|
||||||
}
|
}
|
||||||
@ -471,9 +450,7 @@ class MainActivity : AppCompatActivity(), ListSelectionListener<Serializable> {
|
|||||||
// for the selected item ID.
|
// for the selected item ID.
|
||||||
val detailIntent = when (item) {
|
val detailIntent = when (item) {
|
||||||
is Plaintext -> {
|
is Plaintext -> {
|
||||||
Intent(this, MessageDetailActivity::class.java).apply {
|
Intent(this, MessageDetailActivity::class.java)
|
||||||
putExtra(EXTRA_SHOW_LABEL, selectedLabel)
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
is BitmessageAddress -> Intent(this, AddressDetailActivity::class.java)
|
is BitmessageAddress -> Intent(this, AddressDetailActivity::class.java)
|
||||||
else -> throw IllegalArgumentException("Plaintext or BitmessageAddress expected, but was ${item::class.simpleName}")
|
else -> throw IllegalArgumentException("Plaintext or BitmessageAddress expected, but was ${item::class.simpleName}")
|
||||||
|
@ -5,8 +5,6 @@ import android.os.Bundle
|
|||||||
import android.support.v4.app.NavUtils
|
import android.support.v4.app.NavUtils
|
||||||
import android.view.MenuItem
|
import android.view.MenuItem
|
||||||
|
|
||||||
import ch.dissem.bitmessage.entity.valueobject.Label
|
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* An activity representing a single Message detail screen. This
|
* An activity representing a single Message detail screen. This
|
||||||
@ -18,7 +16,6 @@ import ch.dissem.bitmessage.entity.valueobject.Label
|
|||||||
* more than a [MessageDetailFragment].
|
* more than a [MessageDetailFragment].
|
||||||
*/
|
*/
|
||||||
class MessageDetailActivity : DetailActivity() {
|
class MessageDetailActivity : DetailActivity() {
|
||||||
private var label: Label? = null
|
|
||||||
|
|
||||||
override fun onCreate(savedInstanceState: Bundle?) {
|
override fun onCreate(savedInstanceState: Bundle?) {
|
||||||
super.onCreate(savedInstanceState)
|
super.onCreate(savedInstanceState)
|
||||||
@ -33,7 +30,6 @@ class MessageDetailActivity : DetailActivity() {
|
|||||||
// http://developer.android.com/guide/components/fragments.html
|
// http://developer.android.com/guide/components/fragments.html
|
||||||
//
|
//
|
||||||
if (savedInstanceState == null) {
|
if (savedInstanceState == null) {
|
||||||
label = intent.getSerializableExtra(MainActivity.EXTRA_SHOW_LABEL) as Label?
|
|
||||||
// Create the detail fragment and add it to the activity
|
// Create the detail fragment and add it to the activity
|
||||||
// using a fragment transaction.
|
// using a fragment transaction.
|
||||||
val arguments = Bundle()
|
val arguments = Bundle()
|
||||||
@ -49,9 +45,7 @@ class MessageDetailActivity : DetailActivity() {
|
|||||||
|
|
||||||
override fun onOptionsItemSelected(item: MenuItem) = when (item.itemId) {
|
override fun onOptionsItemSelected(item: MenuItem) = when (item.itemId) {
|
||||||
android.R.id.home -> {
|
android.R.id.home -> {
|
||||||
val parentIntent = Intent(this, MainActivity::class.java)
|
NavUtils.navigateUpTo(this, Intent(this, MainActivity::class.java))
|
||||||
parentIntent.putExtra(MainActivity.EXTRA_SHOW_LABEL, label)
|
|
||||||
NavUtils.navigateUpTo(this, parentIntent)
|
|
||||||
true
|
true
|
||||||
}
|
}
|
||||||
else -> super.onOptionsItemSelected(item)
|
else -> super.onOptionsItemSelected(item)
|
||||||
|
@ -32,6 +32,7 @@ import ch.dissem.apps.abit.adapter.SwipeableMessageAdapter
|
|||||||
import ch.dissem.apps.abit.listener.ListSelectionListener
|
import ch.dissem.apps.abit.listener.ListSelectionListener
|
||||||
import ch.dissem.apps.abit.repository.AndroidMessageRepository
|
import ch.dissem.apps.abit.repository.AndroidMessageRepository
|
||||||
import ch.dissem.apps.abit.service.Singleton
|
import ch.dissem.apps.abit.service.Singleton
|
||||||
|
import ch.dissem.apps.abit.service.Singleton.currentLabel
|
||||||
import ch.dissem.apps.abit.util.FabUtils
|
import ch.dissem.apps.abit.util.FabUtils
|
||||||
import ch.dissem.bitmessage.entity.Plaintext
|
import ch.dissem.bitmessage.entity.Plaintext
|
||||||
import ch.dissem.bitmessage.entity.valueobject.Label
|
import ch.dissem.bitmessage.entity.valueobject.Label
|
||||||
@ -87,8 +88,6 @@ class MessageListFragment : Fragment(), ListHolder<Label> {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
override var currentLabel: Label? = null
|
|
||||||
|
|
||||||
private var emptyTrashMenuItem: MenuItem? = null
|
private var emptyTrashMenuItem: MenuItem? = null
|
||||||
private lateinit var messageRepo: AndroidMessageRepository
|
private lateinit var messageRepo: AndroidMessageRepository
|
||||||
private var activateOnItemClick: Boolean = false
|
private var activateOnItemClick: Boolean = false
|
||||||
@ -99,7 +98,7 @@ class MessageListFragment : Fragment(), ListHolder<Label> {
|
|||||||
isLoading = true
|
isLoading = true
|
||||||
swipeableMessageAdapter?.let { messageAdapter ->
|
swipeableMessageAdapter?.let { messageAdapter ->
|
||||||
doAsync {
|
doAsync {
|
||||||
val messages = messageRepo.findMessages(currentLabel, messageAdapter.itemCount, PAGE_SIZE)
|
val messages = messageRepo.findMessages(currentLabel.value, messageAdapter.itemCount, PAGE_SIZE)
|
||||||
onUiThread {
|
onUiThread {
|
||||||
messageAdapter.addAll(messages)
|
messageAdapter.addAll(messages)
|
||||||
isLoading = false
|
isLoading = false
|
||||||
@ -121,21 +120,13 @@ class MessageListFragment : Fragment(), ListHolder<Label> {
|
|||||||
initFab(activity)
|
initFab(activity)
|
||||||
messageRepo = Singleton.getMessageRepository(activity)
|
messageRepo = Singleton.getMessageRepository(activity)
|
||||||
|
|
||||||
if (backStack.isEmpty() && currentLabel == null) {
|
currentLabel.addObserver(this) { new -> doUpdateList(new) }
|
||||||
doUpdateList(activity.selectedLabel)
|
doUpdateList(currentLabel.value)
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun updateList(label: Label) {
|
override fun onPause() {
|
||||||
if (currentLabel != null && currentLabel != label && (backStack.isEmpty() || currentLabel != backStack.peek())) {
|
currentLabel.removeObserver(this)
|
||||||
backStack.push(currentLabel)
|
super.onPause()
|
||||||
}
|
|
||||||
if (!isResumed) {
|
|
||||||
currentLabel = label
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
doUpdateList(label)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun doUpdateList(label: Label?) {
|
private fun doUpdateList(label: Label?) {
|
||||||
@ -146,7 +137,6 @@ class MessageListFragment : Fragment(), ListHolder<Label> {
|
|||||||
swipeableMessageAdapter?.notifyDataSetChanged()
|
swipeableMessageAdapter?.notifyDataSetChanged()
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
currentLabel = label
|
|
||||||
emptyTrashMenuItem?.isVisible = label.type == Label.Type.TRASH
|
emptyTrashMenuItem?.isVisible = label.type == Label.Type.TRASH
|
||||||
mainActivity?.apply {
|
mainActivity?.apply {
|
||||||
if ("archive" == label.toString()) {
|
if ("archive" == label.toString()) {
|
||||||
@ -238,36 +228,7 @@ class MessageListFragment : Fragment(), ListHolder<Label> {
|
|||||||
recyclerViewSwipeManager = swipeManager
|
recyclerViewSwipeManager = swipeManager
|
||||||
this.swipeableMessageAdapter = adapter
|
this.swipeableMessageAdapter = adapter
|
||||||
|
|
||||||
Singleton.labeler.listener = { message, added, removed ->
|
Singleton.updateMessageListAdapterInListener(adapter)
|
||||||
swipeableMessageAdapter?.let { swipeableMessageAdapter ->
|
|
||||||
when {
|
|
||||||
currentLabel?.type == Label.Type.TRASH && added.all { it.type == Label.Type.TRASH } && removed.any { it.type == Label.Type.TRASH } -> {
|
|
||||||
// work-around for messages that are deleted from trash
|
|
||||||
swipeableMessageAdapter.remove(message)
|
|
||||||
}
|
|
||||||
currentLabel?.type == Label.Type.UNREAD && added.all { it.type == Label.Type.TRASH } -> {
|
|
||||||
// work-around for messages that are deleted from unread, which already have the unread label removed
|
|
||||||
swipeableMessageAdapter.remove(message)
|
|
||||||
}
|
|
||||||
added.contains(currentLabel) -> {
|
|
||||||
// in most cases, top should be the correct position, but time will show if
|
|
||||||
// the message should be properly sorted in
|
|
||||||
swipeableMessageAdapter.addFirst(message)
|
|
||||||
}
|
|
||||||
removed.contains(currentLabel) -> {
|
|
||||||
swipeableMessageAdapter.remove(message)
|
|
||||||
}
|
|
||||||
removed.any { it.type == Label.Type.UNREAD } || added.any { it.type == Label.Type.UNREAD } -> {
|
|
||||||
swipeableMessageAdapter.update(message)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if (removed.any { it.type == Label.Type.UNREAD } || added.any { it.type == Label.Type.UNREAD }) {
|
|
||||||
MainActivity.apply {
|
|
||||||
updateUnread()
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun initFab(context: MainActivity) {
|
private fun initFab(context: MainActivity) {
|
||||||
@ -326,24 +287,27 @@ class MessageListFragment : Fragment(), ListHolder<Label> {
|
|||||||
}
|
}
|
||||||
|
|
||||||
override fun onOptionsItemSelected(item: MenuItem): Boolean {
|
override fun onOptionsItemSelected(item: MenuItem): Boolean {
|
||||||
currentLabel?.let { currentLabel ->
|
|
||||||
when (item.itemId) {
|
when (item.itemId) {
|
||||||
R.id.empty_trash -> {
|
R.id.empty_trash -> {
|
||||||
if (currentLabel.type != Label.Type.TRASH) return true
|
currentLabel.value?.let { label ->
|
||||||
|
if (label.type != Label.Type.TRASH) return true
|
||||||
|
|
||||||
doAsync {
|
doAsync {
|
||||||
for (message in messageRepo.findMessages(currentLabel)) {
|
for (message in messageRepo.findMessages(label)) {
|
||||||
messageRepo.remove(message)
|
messageRepo.remove(message)
|
||||||
}
|
}
|
||||||
|
|
||||||
uiThread { updateList(currentLabel) }
|
uiThread { doUpdateList(label) }
|
||||||
|
}
|
||||||
}
|
}
|
||||||
return true
|
return true
|
||||||
}
|
}
|
||||||
else -> return false
|
else -> return false
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return false
|
|
||||||
|
override fun updateList(label: Label) {
|
||||||
|
currentLabel.value = label
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun setActivateOnItemClick(activateOnItemClick: Boolean) {
|
override fun setActivateOnItemClick(activateOnItemClick: Boolean) {
|
||||||
@ -354,7 +318,7 @@ class MessageListFragment : Fragment(), ListHolder<Label> {
|
|||||||
override fun showPreviousList() = if (backStack.isEmpty()) {
|
override fun showPreviousList() = if (backStack.isEmpty()) {
|
||||||
false
|
false
|
||||||
} else {
|
} else {
|
||||||
doUpdateList(backStack.pop())
|
currentLabel.value = backStack.pop()
|
||||||
true
|
true
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -21,14 +21,17 @@ import android.widget.Toast
|
|||||||
import ch.dissem.apps.abit.MainActivity
|
import ch.dissem.apps.abit.MainActivity
|
||||||
import ch.dissem.apps.abit.R
|
import ch.dissem.apps.abit.R
|
||||||
import ch.dissem.apps.abit.adapter.AndroidCryptography
|
import ch.dissem.apps.abit.adapter.AndroidCryptography
|
||||||
|
import ch.dissem.apps.abit.adapter.SwipeableMessageAdapter
|
||||||
import ch.dissem.apps.abit.adapter.SwitchingProofOfWorkEngine
|
import ch.dissem.apps.abit.adapter.SwitchingProofOfWorkEngine
|
||||||
import ch.dissem.apps.abit.listener.MessageListener
|
import ch.dissem.apps.abit.listener.MessageListener
|
||||||
import ch.dissem.apps.abit.pow.ServerPowEngine
|
import ch.dissem.apps.abit.pow.ServerPowEngine
|
||||||
import ch.dissem.apps.abit.repository.*
|
import ch.dissem.apps.abit.repository.*
|
||||||
import ch.dissem.apps.abit.util.Constants
|
import ch.dissem.apps.abit.util.Constants
|
||||||
|
import ch.dissem.apps.abit.util.Observable
|
||||||
import ch.dissem.bitmessage.BitmessageContext
|
import ch.dissem.bitmessage.BitmessageContext
|
||||||
import ch.dissem.bitmessage.entity.BitmessageAddress
|
import ch.dissem.bitmessage.entity.BitmessageAddress
|
||||||
import ch.dissem.bitmessage.entity.payload.Pubkey
|
import ch.dissem.bitmessage.entity.payload.Pubkey
|
||||||
|
import ch.dissem.bitmessage.entity.valueobject.Label
|
||||||
import ch.dissem.bitmessage.networking.nio.NioNetworkHandler
|
import ch.dissem.bitmessage.networking.nio.NioNetworkHandler
|
||||||
import ch.dissem.bitmessage.ports.DefaultLabeler
|
import ch.dissem.bitmessage.ports.DefaultLabeler
|
||||||
import ch.dissem.bitmessage.utils.ConversationService
|
import ch.dissem.bitmessage.utils.ConversationService
|
||||||
@ -36,12 +39,54 @@ import ch.dissem.bitmessage.utils.TTL
|
|||||||
import ch.dissem.bitmessage.utils.UnixTime.DAY
|
import ch.dissem.bitmessage.utils.UnixTime.DAY
|
||||||
import org.jetbrains.anko.doAsync
|
import org.jetbrains.anko.doAsync
|
||||||
import org.jetbrains.anko.uiThread
|
import org.jetbrains.anko.uiThread
|
||||||
|
import java.lang.ref.WeakReference
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Provides singleton objects across the application.
|
* Provides singleton objects across the application.
|
||||||
*/
|
*/
|
||||||
object Singleton {
|
object Singleton {
|
||||||
val labeler = DefaultLabeler()
|
var currentLabel = Observable<Label?>(null).apply {
|
||||||
|
addObserver(this) { _ -> swipeableMessageAdapter = null }
|
||||||
|
}
|
||||||
|
|
||||||
|
private var swipeableMessageAdapter: WeakReference<SwipeableMessageAdapter>? = null
|
||||||
|
val labeler = DefaultLabeler().apply {
|
||||||
|
listener = { message, added, removed ->
|
||||||
|
swipeableMessageAdapter?.get()?.let { swipeableMessageAdapter ->
|
||||||
|
currentLabel.value?.let { label ->
|
||||||
|
when {
|
||||||
|
label.type == Label.Type.TRASH
|
||||||
|
&& added.all { it.type == Label.Type.TRASH }
|
||||||
|
&& removed.any { it.type == Label.Type.TRASH } -> {
|
||||||
|
// work-around for messages that are deleted from trash
|
||||||
|
swipeableMessageAdapter.remove(message)
|
||||||
|
}
|
||||||
|
label.type == Label.Type.UNREAD
|
||||||
|
&& added.all { it.type == Label.Type.TRASH } -> {
|
||||||
|
// work-around for messages that are deleted from unread, which already have the unread label removed
|
||||||
|
swipeableMessageAdapter.remove(message)
|
||||||
|
}
|
||||||
|
added.contains(label) -> {
|
||||||
|
// in most cases, top should be the correct position, but time will show if
|
||||||
|
// the message should be properly sorted in
|
||||||
|
swipeableMessageAdapter.addFirst(message)
|
||||||
|
}
|
||||||
|
removed.contains(label) -> {
|
||||||
|
swipeableMessageAdapter.remove(message)
|
||||||
|
}
|
||||||
|
removed.any { it.type == Label.Type.UNREAD } || added.any { it.type == Label.Type.UNREAD } -> {
|
||||||
|
swipeableMessageAdapter.update(message)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (removed.any { it.type == Label.Type.UNREAD } || added.any { it.type == Label.Type.UNREAD }) {
|
||||||
|
MainActivity.apply {
|
||||||
|
updateUnread()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
var bitmessageContext: BitmessageContext? = null
|
var bitmessageContext: BitmessageContext? = null
|
||||||
private set
|
private set
|
||||||
private var conversationService: ConversationService? = null
|
private var conversationService: ConversationService? = null
|
||||||
@ -75,6 +120,10 @@ object Singleton {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fun updateMessageListAdapterInListener(adapter: SwipeableMessageAdapter) {
|
||||||
|
swipeableMessageAdapter = WeakReference(adapter)
|
||||||
|
}
|
||||||
|
|
||||||
fun getMessageListener(ctx: Context) = init({ messageListener }, { messageListener = it }) { MessageListener(ctx) }
|
fun getMessageListener(ctx: Context) = init({ messageListener }, { messageListener = it }) { MessageListener(ctx) }
|
||||||
|
|
||||||
fun getLabelRepository(ctx: Context) = getBitmessageContext(ctx).labels as AndroidLabelRepository
|
fun getLabelRepository(ctx: Context) = getBitmessageContext(ctx).labels as AndroidLabelRepository
|
||||||
|
37
app/src/main/java/ch/dissem/apps/abit/util/Observable.kt
Normal file
37
app/src/main/java/ch/dissem/apps/abit/util/Observable.kt
Normal file
@ -0,0 +1,37 @@
|
|||||||
|
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.put(key, observer)
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Remove the observer that was registered with the given key.
|
||||||
|
*/
|
||||||
|
fun removeObserver(key: Any) {
|
||||||
|
observers.remove(key)
|
||||||
|
}
|
||||||
|
}
|
Loading…
Reference in New Issue
Block a user