From b6cb19ee4251242376753b94c8d5737a3b32a359 Mon Sep 17 00:00:00 2001
From: Janne Koschinski <janne@kuschku.de>
Date: Mon, 2 Apr 2018 00:02:42 +0200
Subject: [PATCH] Chatlist editing works reliably

---
 .../coresettings/chatlist/ChatListFragment.kt | 125 +++++++++++++++---
 .../chatlist/MinimumActivityAdapter.kt        |  71 ++++++++++
 .../chatlist/MinimumActivityItem.kt           |   6 +
 .../coresettings/chatlist/NetworkAdapter.kt   |  74 +++++++++++
 app/src/main/res/layout/settings_chatlist.xml |  14 +-
 .../main/res/values-de/strings_settings.xml   |   6 +-
 app/src/main/res/values/strings_settings.xml  |   6 +-
 .../kuschku/libquassel/quassel/BufferInfo.kt  |   2 +-
 .../quassel/syncables/BufferViewConfig.kt     |   5 +
 9 files changed, 286 insertions(+), 23 deletions(-)
 create mode 100644 app/src/main/java/de/kuschku/quasseldroid/ui/coresettings/chatlist/MinimumActivityAdapter.kt
 create mode 100644 app/src/main/java/de/kuschku/quasseldroid/ui/coresettings/chatlist/MinimumActivityItem.kt
 create mode 100644 app/src/main/java/de/kuschku/quasseldroid/ui/coresettings/chatlist/NetworkAdapter.kt

diff --git a/app/src/main/java/de/kuschku/quasseldroid/ui/coresettings/chatlist/ChatListFragment.kt b/app/src/main/java/de/kuschku/quasseldroid/ui/coresettings/chatlist/ChatListFragment.kt
index c38a27a9c..0aa9084b8 100644
--- a/app/src/main/java/de/kuschku/quasseldroid/ui/coresettings/chatlist/ChatListFragment.kt
+++ b/app/src/main/java/de/kuschku/quasseldroid/ui/coresettings/chatlist/ChatListFragment.kt
@@ -6,12 +6,22 @@ import android.support.v7.widget.SwitchCompat
 import android.view.LayoutInflater
 import android.view.View
 import android.view.ViewGroup
+import android.widget.AdapterView
+import android.widget.Spinner
 import android.widget.TextView
 import butterknife.BindView
 import butterknife.ButterKnife
+import de.kuschku.libquassel.protocol.Buffer_Activity
+import de.kuschku.libquassel.protocol.Buffer_Type
 import de.kuschku.libquassel.quassel.syncables.BufferViewConfig
+import de.kuschku.libquassel.quassel.syncables.Network
+import de.kuschku.libquassel.quassel.syncables.interfaces.INetwork
+import de.kuschku.libquassel.util.flag.hasFlag
+import de.kuschku.libquassel.util.flag.minus
+import de.kuschku.libquassel.util.flag.plus
 import de.kuschku.quasseldroid.R
 import de.kuschku.quasseldroid.ui.coresettings.SettingsFragment
+import de.kuschku.quasseldroid.util.helper.combineLatest
 import de.kuschku.quasseldroid.util.helper.toLiveData
 import io.reactivex.Observable
 
@@ -30,8 +40,11 @@ class ChatListFragment : SettingsFragment() {
   @BindView(R.id.add_new_buffers_automatically)
   lateinit var addNewBuffersAutomatically: SwitchCompat
 
-  @BindView(R.id.disable_decoration)
-  lateinit var disableDecoration: SwitchCompat
+  @BindView(R.id.network_id)
+  lateinit var networkId: Spinner
+
+  @BindView(R.id.show_status_buffer)
+  lateinit var showStatusBuffer: SwitchCompat
 
   @BindView(R.id.show_channels)
   lateinit var showChannels: SwitchCompat
@@ -39,6 +52,9 @@ class ChatListFragment : SettingsFragment() {
   @BindView(R.id.show_queries)
   lateinit var showQueries: SwitchCompat
 
+  @BindView(R.id.minimum_activity)
+  lateinit var minimumActivity: Spinner
+
   @BindView(R.id.hide_inactive_buffers)
   lateinit var hideInactiveBuffers: SwitchCompat
 
@@ -52,24 +68,86 @@ class ChatListFragment : SettingsFragment() {
 
     val chatlistId = arguments?.getInt("chatlist", -1) ?: -1
 
-    viewModel.bufferViewConfigMap.switchMap {
-      it[chatlistId]?.liveUpdates() ?: Observable.empty()
-    }.firstElement()
-      .toLiveData().observe(this, Observer {
-        if (it != null) {
-          this.chatlist = Pair(it, it.copy())
+    val minimumActivityAdapter = MinimumActivityAdapter(listOf(
+      MinimumActivityItem(
+        activity = Buffer_Activity.NoActivity,
+        name = R.string.settings_chatlist_minimum_activity_no_activity
+      ),
+      MinimumActivityItem(
+        activity = Buffer_Activity.OtherActivity,
+        name = R.string.settings_chatlist_minimum_activity_other_activity
+      ),
+      MinimumActivityItem(
+        activity = Buffer_Activity.NewMessage,
+        name = R.string.settings_chatlist_minimum_activity_new_message
+      ),
+      MinimumActivityItem(
+        activity = Buffer_Activity.Highlight,
+        name = R.string.settings_chatlist_minimum_activity_highlight
+      )
+    ))
+    minimumActivity.adapter = minimumActivityAdapter
+
+    val networkAdapter = NetworkAdapter()
+    networkId.adapter = networkAdapter
+
+    viewModel.networks.switchMap {
+      combineLatest(it.values.map(Network::liveNetworkInfo)).map {
+        it.sortedBy(INetwork.NetworkInfo::networkName)
+      }
+    }.toLiveData().observe(this, Observer {
+      if (it != null) {
+        val selectOriginal = networkId.selectedItemId == Spinner.INVALID_ROW_ID
+        networkAdapter.submitList(listOf(null) + it)
+        if (selectOriginal) {
           this.chatlist?.let { (_, data) ->
-            bufferViewName.text = data.bufferViewName()
-            showSearch.isChecked = data.showSearch()
-            sortAlphabetically.isChecked = data.sortAlphabetically()
-            addNewBuffersAutomatically.isChecked = data.addNewBuffersAutomatically()
-            disableDecoration.isChecked = data.disableDecoration()
-
-            hideInactiveBuffers.isChecked = data.hideInactiveBuffers()
-            hideInactiveNetworks.isChecked = data.hideInactiveNetworks()
+            networkAdapter.indexOf(data.networkId())?.let(networkId::setSelection)
           }
         }
-      })
+      }
+    })
+
+    viewModel.bufferViewConfigMap.switchMap {
+      it[chatlistId]?.liveUpdates() ?: Observable.empty()
+    }.firstElement().toLiveData().observe(this, Observer {
+      if (it != null) {
+        this.chatlist = Pair(it, it.copy())
+        this.chatlist?.let { (_, data) ->
+          bufferViewName.text = data.bufferViewName()
+          showSearch.isChecked = data.showSearch()
+          sortAlphabetically.isChecked = data.sortAlphabetically()
+          addNewBuffersAutomatically.isChecked = data.addNewBuffersAutomatically()
+          showStatusBuffer.isChecked = data.allowedBufferTypes().hasFlag(Buffer_Type.StatusBuffer)
+
+          minimumActivity.setSelection(
+            minimumActivityAdapter.indexOf(data.minimumActivity()) ?: 0
+          )
+
+          networkAdapter.indexOf(data.networkId())?.let(networkId::setSelection)
+
+          hideInactiveBuffers.isChecked = data.hideInactiveBuffers()
+          hideInactiveNetworks.isChecked = data.hideInactiveNetworks()
+
+          showQueries.isChecked = data.allowedBufferTypes().hasFlag(Buffer_Type.QueryBuffer)
+          showChannels.isChecked = data.allowedBufferTypes().hasFlag(Buffer_Type.ChannelBuffer)
+        }
+      }
+    })
+    networkId.onItemSelectedListener = object : AdapterView.OnItemSelectedListener {
+      override fun onNothingSelected(parent: AdapterView<*>?) {
+        showStatusBuffer.isChecked = true
+        showStatusBuffer.isEnabled = false
+      }
+
+      override fun onItemSelected(parent: AdapterView<*>?, view: View?, position: Int, id: Long) {
+        if (id == -1L) {
+          showStatusBuffer.isChecked = true
+          showStatusBuffer.isEnabled = false
+        } else {
+          showStatusBuffer.isEnabled = true
+        }
+      }
+    }
 
     return view
   }
@@ -79,11 +157,22 @@ class ChatListFragment : SettingsFragment() {
     data.setShowSearch(showSearch.isChecked)
     data.setSortAlphabetically(sortAlphabetically.isChecked)
     data.setAddNewBuffersAutomatically(addNewBuffersAutomatically.isChecked)
-    data.setDisableDecoration(disableDecoration.isChecked)
 
     data.setHideInactiveBuffers(hideInactiveBuffers.isChecked)
     data.setHideInactiveNetworks(hideInactiveNetworks.isChecked)
 
+    var allowedBufferTypes = data.allowedBufferTypes()
+    if (showQueries.isChecked) allowedBufferTypes += Buffer_Type.QueryBuffer
+    else allowedBufferTypes -= Buffer_Type.QueryBuffer
+    if (showChannels.isChecked) allowedBufferTypes += Buffer_Type.ChannelBuffer
+    else allowedBufferTypes -= Buffer_Type.ChannelBuffer
+    if (showStatusBuffer.isChecked) allowedBufferTypes += Buffer_Type.StatusBuffer
+    else allowedBufferTypes -= Buffer_Type.StatusBuffer
+    data.setAllowedBufferTypes(allowedBufferTypes)
+
+    data.setNetworkId(networkId.selectedItemId.toInt())
+    data.setMinimumActivity(minimumActivity.selectedItemId.toInt())
+
     it.requestUpdate(data.toVariantMap())
     true
   } ?: false
diff --git a/app/src/main/java/de/kuschku/quasseldroid/ui/coresettings/chatlist/MinimumActivityAdapter.kt b/app/src/main/java/de/kuschku/quasseldroid/ui/coresettings/chatlist/MinimumActivityAdapter.kt
new file mode 100644
index 000000000..2a36ed6f6
--- /dev/null
+++ b/app/src/main/java/de/kuschku/quasseldroid/ui/coresettings/chatlist/MinimumActivityAdapter.kt
@@ -0,0 +1,71 @@
+package de.kuschku.quasseldroid.ui.coresettings.chatlist
+
+import android.support.v7.widget.RecyclerView
+import android.support.v7.widget.ThemedSpinnerAdapter
+import android.view.LayoutInflater
+import android.view.View
+import android.view.ViewGroup
+import android.widget.TextView
+import butterknife.BindView
+import butterknife.ButterKnife
+import de.kuschku.libquassel.protocol.Buffer_Activities
+import de.kuschku.quasseldroid.R
+import de.kuschku.quasseldroid.util.ui.ContextThemeWrapper
+import de.kuschku.quasseldroid.util.ui.RecyclerSpinnerAdapter
+
+class MinimumActivityAdapter(val data: List<MinimumActivityItem>) :
+  RecyclerSpinnerAdapter<MinimumActivityAdapter.MinimumActivityViewHolder>(),
+  ThemedSpinnerAdapter {
+
+  override fun isEmpty() = data.isEmpty()
+
+  override fun onBindViewHolder(holder: MinimumActivityViewHolder, position: Int) =
+    holder.bind(getItem(position))
+
+  override fun onCreateViewHolder(parent: ViewGroup, dropDown: Boolean)
+    : MinimumActivityViewHolder {
+    val inflater = LayoutInflater.from(
+      if (dropDown)
+        ContextThemeWrapper(parent.context, dropDownViewTheme)
+      else
+        parent.context
+    )
+    val view = inflater.inflate(R.layout.widget_spinner_item_toolbar, parent, false)
+    return MinimumActivityViewHolder(
+      view
+    )
+  }
+
+  override fun getItem(position: Int) = data[position]
+
+  override fun getItemId(position: Int) = getItem(position).activity.toInt().toLong()
+
+  override fun hasStableIds() = true
+
+  override fun getCount() = data.size
+
+  fun indexOf(activity: Buffer_Activities): Int? {
+    for ((key, item) in data.withIndex()) {
+      if (item.activity.toInt() == activity.toInt()) {
+        return key
+      }
+    }
+    return null
+  }
+
+  class MinimumActivityViewHolder(itemView: View) : RecyclerView.ViewHolder(itemView) {
+    @BindView(android.R.id.text1)
+    lateinit var text: TextView
+
+    init {
+      ButterKnife.bind(this, itemView)
+    }
+
+    fun bind(activity: MinimumActivityItem?) {
+      activity?.let {
+        text.setText(it.name)
+      }
+    }
+  }
+}
+
diff --git a/app/src/main/java/de/kuschku/quasseldroid/ui/coresettings/chatlist/MinimumActivityItem.kt b/app/src/main/java/de/kuschku/quasseldroid/ui/coresettings/chatlist/MinimumActivityItem.kt
new file mode 100644
index 000000000..7e100cf27
--- /dev/null
+++ b/app/src/main/java/de/kuschku/quasseldroid/ui/coresettings/chatlist/MinimumActivityItem.kt
@@ -0,0 +1,6 @@
+package de.kuschku.quasseldroid.ui.coresettings.chatlist
+
+import android.support.annotation.StringRes
+import de.kuschku.libquassel.protocol.Buffer_Activity
+
+data class MinimumActivityItem(val activity: Buffer_Activity, @StringRes val name: Int)
diff --git a/app/src/main/java/de/kuschku/quasseldroid/ui/coresettings/chatlist/NetworkAdapter.kt b/app/src/main/java/de/kuschku/quasseldroid/ui/coresettings/chatlist/NetworkAdapter.kt
new file mode 100644
index 000000000..c70c42f33
--- /dev/null
+++ b/app/src/main/java/de/kuschku/quasseldroid/ui/coresettings/chatlist/NetworkAdapter.kt
@@ -0,0 +1,74 @@
+package de.kuschku.quasseldroid.ui.coresettings.chatlist
+
+import android.support.v7.widget.RecyclerView
+import android.support.v7.widget.ThemedSpinnerAdapter
+import android.view.LayoutInflater
+import android.view.View
+import android.view.ViewGroup
+import android.widget.TextView
+import butterknife.BindView
+import butterknife.ButterKnife
+import de.kuschku.libquassel.protocol.NetworkId
+import de.kuschku.libquassel.quassel.syncables.interfaces.INetwork
+import de.kuschku.quasseldroid.R
+import de.kuschku.quasseldroid.util.ui.ContextThemeWrapper
+import de.kuschku.quasseldroid.util.ui.RecyclerSpinnerAdapter
+
+class NetworkAdapter : RecyclerSpinnerAdapter<NetworkAdapter.NetworkViewHolder>(),
+                       ThemedSpinnerAdapter {
+  var data = emptyList<INetwork.NetworkInfo?>()
+
+  fun submitList(list: List<INetwork.NetworkInfo?>) {
+    data = list
+    notifyDataSetChanged()
+  }
+
+  override fun isEmpty() = data.isEmpty()
+
+  override fun onBindViewHolder(holder: NetworkViewHolder, position: Int) =
+    holder.bind(getItem(position))
+
+  override fun onCreateViewHolder(parent: ViewGroup, dropDown: Boolean)
+    : NetworkViewHolder {
+    val inflater = LayoutInflater.from(
+      if (dropDown)
+        ContextThemeWrapper(parent.context, dropDownViewTheme)
+      else
+        parent.context
+    )
+    val view = inflater.inflate(R.layout.widget_spinner_item_toolbar, parent, false)
+    return NetworkViewHolder(
+      view
+    )
+  }
+
+  fun indexOf(id: NetworkId): Int? {
+    for ((key, item) in data.withIndex()) {
+      if (item?.networkId ?: -1 == id) {
+        return key
+      }
+    }
+    return null
+  }
+
+  override fun getItem(position: Int): INetwork.NetworkInfo? = data[position]
+
+  override fun getItemId(position: Int) = getItem(position)?.networkId?.toLong() ?: -1
+
+  override fun hasStableIds() = true
+
+  override fun getCount() = data.size
+
+  class NetworkViewHolder(itemView: View) : RecyclerView.ViewHolder(itemView) {
+    @BindView(android.R.id.text1)
+    lateinit var text: TextView
+
+    init {
+      ButterKnife.bind(this, itemView)
+    }
+
+    fun bind(network: INetwork.NetworkInfo?) {
+      text.text = network?.networkName ?: "All"
+    }
+  }
+}
diff --git a/app/src/main/res/layout/settings_chatlist.xml b/app/src/main/res/layout/settings_chatlist.xml
index d930f8e80..773b90fd7 100644
--- a/app/src/main/res/layout/settings_chatlist.xml
+++ b/app/src/main/res/layout/settings_chatlist.xml
@@ -70,10 +70,15 @@
       style="@style/Widget.CoreSettings.DependentGroup"
       android:visibility="visible">
 
+      <Spinner
+        android:id="@+id/network_id"
+        android:layout_width="match_parent"
+        android:layout_height="wrap_content" />
+
       <android.support.v7.widget.SwitchCompat
-        android:id="@+id/disable_decoration"
+        android:id="@+id/show_status_buffer"
         style="@style/Widget.CoreSettings.PrimaryItemSwitch"
-        android:text="@string/settings_chatlist_disable_decoration" />
+        android:text="@string/settings_chatlist_show_status_buffer" />
     </LinearLayout>
 
     <LinearLayout
@@ -123,6 +128,11 @@
       style="@style/Widget.CoreSettings.DependentGroup"
       android:visibility="visible">
 
+      <Spinner
+        android:id="@+id/minimum_activity"
+        android:layout_width="match_parent"
+        android:layout_height="wrap_content" />
+
       <android.support.v7.widget.SwitchCompat
         android:id="@+id/hide_inactive_buffers"
         style="@style/Widget.CoreSettings.PrimaryItemSwitch"
diff --git a/app/src/main/res/values-de/strings_settings.xml b/app/src/main/res/values-de/strings_settings.xml
index e28b1ae6c..90342670a 100644
--- a/app/src/main/res/values-de/strings_settings.xml
+++ b/app/src/main/res/values-de/strings_settings.xml
@@ -27,11 +27,15 @@
   <string name="settings_chatlist_sort_alphabetically">Alphabetisch Sortieren</string>
   <string name="settings_chatlist_add_new_buffers_automatically">Neue Chats automatisch hinzufügen</string>
   <string name="settings_chatlist_network">Netzwerk</string>
-  <string name="settings_chatlist_disable_decoration">Status-Fenster verstecken</string>
+  <string name="settings_chatlist_show_status_buffer">Status-Fenster anzeigen</string>
   <string name="settings_chatlist_types">Chat-Typen</string>
   <string name="settings_chatlist_show_channels">Kanäle anzeigen</string>
   <string name="settings_chatlist_show_queries">Dialoge anzeigen</string>
   <string name="settings_chatlist_activity">Aktivität</string>
+  <string name="settings_chatlist_minimum_activity_no_activity">Keine Aktivität</string>
+  <string name="settings_chatlist_minimum_activity_other_activity">Andere Aktivität</string>
+  <string name="settings_chatlist_minimum_activity_new_message">Neue Nachricht</string>
+  <string name="settings_chatlist_minimum_activity_highlight">Hervorhebung</string>
   <string name="settings_chatlist_hide_inactive_buffers">Inaktive Chats verstecken</string>
   <string name="settings_chatlist_hide_inactive_networks">Inaktive Netzwerke verstecken</string>
 
diff --git a/app/src/main/res/values/strings_settings.xml b/app/src/main/res/values/strings_settings.xml
index 92777c89a..b81143439 100644
--- a/app/src/main/res/values/strings_settings.xml
+++ b/app/src/main/res/values/strings_settings.xml
@@ -27,11 +27,15 @@
   <string name="settings_chatlist_sort_alphabetically">Sort Alphabetically</string>
   <string name="settings_chatlist_add_new_buffers_automatically">Add new chats automatically</string>
   <string name="settings_chatlist_network">Network</string>
-  <string name="settings_chatlist_disable_decoration">Hide Status Buffer</string>
+  <string name="settings_chatlist_show_status_buffer">Show Status Buffer</string>
   <string name="settings_chatlist_types">Chat Types</string>
   <string name="settings_chatlist_show_channels">Show Channels</string>
   <string name="settings_chatlist_show_queries">Show Queries</string>
   <string name="settings_chatlist_activity">Activity</string>
+  <string name="settings_chatlist_minimum_activity_no_activity">No Activity</string>
+  <string name="settings_chatlist_minimum_activity_other_activity">Other Activity</string>
+  <string name="settings_chatlist_minimum_activity_new_message">New Message</string>
+  <string name="settings_chatlist_minimum_activity_highlight">Highlight</string>
   <string name="settings_chatlist_hide_inactive_buffers">Hide Inactive Chats</string>
   <string name="settings_chatlist_hide_inactive_networks">Hide Inactive Networks</string>
 
diff --git a/lib/src/main/java/de/kuschku/libquassel/quassel/BufferInfo.kt b/lib/src/main/java/de/kuschku/libquassel/quassel/BufferInfo.kt
index c5fcf18b3..2c386e303 100644
--- a/lib/src/main/java/de/kuschku/libquassel/quassel/BufferInfo.kt
+++ b/lib/src/main/java/de/kuschku/libquassel/quassel/BufferInfo.kt
@@ -32,7 +32,7 @@ data class BufferInfo(
     NoActivity(0x00),
     OtherActivity(0x01),
     NewMessage(0x02),
-    Highlight(0x40);
+    Highlight(0x04);
 
     companion object : Flags.Factory<Activity> {
       override val NONE = Activity.of()
diff --git a/lib/src/main/java/de/kuschku/libquassel/quassel/syncables/BufferViewConfig.kt b/lib/src/main/java/de/kuschku/libquassel/quassel/syncables/BufferViewConfig.kt
index 1e8a3738f..5296f71be 100644
--- a/lib/src/main/java/de/kuschku/libquassel/quassel/syncables/BufferViewConfig.kt
+++ b/lib/src/main/java/de/kuschku/libquassel/quassel/syncables/BufferViewConfig.kt
@@ -183,6 +183,11 @@ class BufferViewConfig constructor(
     super.setAddNewBuffersAutomatically(addNewBuffersAutomatically)
   }
 
+  fun setAllowedBufferTypes(bufferTypes: Buffer_Types) {
+    _allowedBufferTypes = bufferTypes
+    super.setAllowedBufferTypes(bufferTypes.toInt())
+  }
+
   override fun setAllowedBufferTypes(bufferTypes: Int) {
     _allowedBufferTypes = Buffer_Type.of(bufferTypes.toShort())
     super.setAllowedBufferTypes(bufferTypes)
-- 
GitLab