From 7f0acd03cabca23c19a635585d85ca50bad254d7 Mon Sep 17 00:00:00 2001
From: Janne Koschinski <janne@kuschku.de>
Date: Fri, 8 Jun 2018 19:39:28 +0200
Subject: [PATCH] Improved core info UI

---
 .../ui/chat/info/core/ClientAdapter.kt        | 10 ++++-
 .../ui/chat/info/core/CoreInfoFragment.kt     | 37 ++++++++++++++++---
 .../missingfeatures/MissingFeaturesDialog.kt  | 13 +++++--
 .../main/res/layout/fragment_info_core.xml    |  7 ++++
 4 files changed, 58 insertions(+), 9 deletions(-)

diff --git a/app/src/main/java/de/kuschku/quasseldroid/ui/chat/info/core/ClientAdapter.kt b/app/src/main/java/de/kuschku/quasseldroid/ui/chat/info/core/ClientAdapter.kt
index c31f492dd..f04876edc 100644
--- a/app/src/main/java/de/kuschku/quasseldroid/ui/chat/info/core/ClientAdapter.kt
+++ b/app/src/main/java/de/kuschku/quasseldroid/ui/chat/info/core/ClientAdapter.kt
@@ -20,6 +20,9 @@ import de.kuschku.quasseldroid.util.helper.getVectorDrawableCompat
 import de.kuschku.quasseldroid.util.helper.styledAttributes
 import de.kuschku.quasseldroid.util.helper.tint
 import de.kuschku.quasseldroid.util.helper.visibleIf
+import org.threeten.bp.ZoneId
+import org.threeten.bp.format.DateTimeFormatter
+import org.threeten.bp.format.FormatStyle
 
 class ClientAdapter : ListAdapter<CoreInfo.ConnectedClientData, ClientAdapter.ClientViewHolder>(
   object : DiffUtil.ItemCallback<CoreInfo.ConnectedClientData>() {
@@ -41,14 +44,18 @@ class ClientAdapter : ListAdapter<CoreInfo.ConnectedClientData, ClientAdapter.Cl
 
   override fun onCreateViewHolder(parent: ViewGroup, viewType: Int) = ClientViewHolder(
     LayoutInflater.from(parent.context).inflate(R.layout.widget_client, parent, false),
+    dateTimeFormatter,
     ::disconnect
   )
 
+  private val dateTimeFormatter = DateTimeFormatter.ofLocalizedDateTime(FormatStyle.MEDIUM)
+
   override fun onBindViewHolder(holder: ClientViewHolder, position: Int) =
     holder.bind(getItem(position))
 
   class ClientViewHolder(
     itemView: View,
+    private val dateTimeFormatter: DateTimeFormatter,
     private val disconnectListener: (Int) -> Unit
   ) : RecyclerView.ViewHolder(itemView) {
 
@@ -97,8 +104,9 @@ class ClientAdapter : ListAdapter<CoreInfo.ConnectedClientData, ClientAdapter.Cl
 
       ip.text = data.remoteAddress
       version.text = Html.fromHtml(data.clientVersion)
+      val connectedSinceFormatted = dateTimeFormatter.format(data.connectedSince.atZone(ZoneId.systemDefault()))
       uptime.text = itemView.context.getString(R.string.label_core_connected_since,
-                                               data.connectedSince.toString())
+                                               connectedSinceFormatted)
       location.text = data.location
       location.visibleIf(data.location.isNotBlank())
 
diff --git a/app/src/main/java/de/kuschku/quasseldroid/ui/chat/info/core/CoreInfoFragment.kt b/app/src/main/java/de/kuschku/quasseldroid/ui/chat/info/core/CoreInfoFragment.kt
index a6a356a5d..63bd080f6 100644
--- a/app/src/main/java/de/kuschku/quasseldroid/ui/chat/info/core/CoreInfoFragment.kt
+++ b/app/src/main/java/de/kuschku/quasseldroid/ui/chat/info/core/CoreInfoFragment.kt
@@ -27,15 +27,23 @@ import android.text.Html
 import android.view.LayoutInflater
 import android.view.View
 import android.view.ViewGroup
+import android.widget.Button
 import android.widget.ImageView
 import android.widget.TextView
 import butterknife.BindView
 import butterknife.ButterKnife
+import de.kuschku.libquassel.quassel.QuasselFeatures
 import de.kuschku.libquassel.util.helpers.value
 import de.kuschku.quasseldroid.R
 import de.kuschku.quasseldroid.ssl.X509Helper
 import de.kuschku.quasseldroid.util.helper.*
+import de.kuschku.quasseldroid.util.missingfeatures.MissingFeature
+import de.kuschku.quasseldroid.util.missingfeatures.MissingFeaturesDialog
+import de.kuschku.quasseldroid.util.missingfeatures.RequiredFeatures
 import de.kuschku.quasseldroid.util.service.ServiceBoundFragment
+import org.threeten.bp.ZoneId
+import org.threeten.bp.format.DateTimeFormatter
+import org.threeten.bp.format.FormatStyle
 
 class CoreInfoFragment : ServiceBoundFragment() {
 
@@ -45,6 +53,9 @@ class CoreInfoFragment : ServiceBoundFragment() {
   @BindView(R.id.version_date)
   lateinit var versionDate: TextView
 
+  @BindView(R.id.missing_features)
+  lateinit var missingFeatures: Button
+
   @BindView(R.id.uptime_container)
   lateinit var uptimeContainer: View
 
@@ -63,22 +74,38 @@ class CoreInfoFragment : ServiceBoundFragment() {
   @BindView(R.id.clients)
   lateinit var clients: RecyclerView
 
+  private val dateTimeFormatter = DateTimeFormatter.ofLocalizedDateTime(FormatStyle.MEDIUM)
+
   override fun onCreateView(inflater: LayoutInflater, container: ViewGroup?,
                             savedInstanceState: Bundle?): View? {
     val view = inflater.inflate(R.layout.fragment_info_core, container, false)
     ButterKnife.bind(this, view)
 
+    var missingFeatureList: List<MissingFeature> = emptyList()
     viewModel.coreInfo.toLiveData().observe(this, Observer {
-      it?.orNull().let {
-        version.text = it?.quasselVersion?.let(Html::fromHtml)
-        versionDate.text = it?.quasselBuildDate?.let(Html::fromHtml)
-
-        val startTime = it?.startTime?.toString()
+      it?.orNull().let { data ->
+        version.text = data?.quasselVersion?.let(Html::fromHtml)
+        versionDate.text = data?.quasselBuildDate?.let(Html::fromHtml)
+
+        val features = viewModel.session.value?.orNull()?.features?.core
+                       ?: QuasselFeatures.empty()
+        missingFeatureList = RequiredFeatures.features.filter {
+          it.feature !in features.enabledFeatures
+        }
+        missingFeatures.visibleIf(missingFeatureList.isNotEmpty())
+
+        val startTime = data?.startTime?.atZone(ZoneId.systemDefault())?.let(dateTimeFormatter::format)
         uptime.text = requireContext().getString(R.string.label_core_online_since,
                                                  startTime.toString())
         uptimeContainer.visibleIf(startTime != null)
       }
     })
+    missingFeatures.setOnClickListener {
+      MissingFeaturesDialog.Builder(requireActivity())
+        .missingFeatures(missingFeatureList)
+        .readOnly(true)
+        .show()
+    }
 
     val secure = requireContext().getVectorDrawableCompat(R.drawable.ic_lock)?.mutate()
     val partiallySecure = requireContext().getVectorDrawableCompat(R.drawable.ic_lock)?.mutate()
diff --git a/app/src/main/java/de/kuschku/quasseldroid/util/missingfeatures/MissingFeaturesDialog.kt b/app/src/main/java/de/kuschku/quasseldroid/util/missingfeatures/MissingFeaturesDialog.kt
index 58b3cf2df..d56ac3302 100644
--- a/app/src/main/java/de/kuschku/quasseldroid/util/missingfeatures/MissingFeaturesDialog.kt
+++ b/app/src/main/java/de/kuschku/quasseldroid/util/missingfeatures/MissingFeaturesDialog.kt
@@ -44,9 +44,10 @@ class MissingFeaturesDialog : DialogFragment() {
     val dialog = MaterialDialog.Builder(requireContext())
       .customView(R.layout.dialog_missing_features, true)
       .title(R.string.label_missing_features)
-      .positiveText(R.string.label_accept)
-      .also { dialog ->
-        builder?.positiveListener?.let(dialog::onPositive)
+      .also {
+        it.positiveText(if (builder?.readOnly == true) R.string.label_accept
+                        else R.string.label_close)
+        builder?.positiveListener?.let(it::onPositive)
       }
       .build()
     ButterKnife.bind(this, dialog.customView!!)
@@ -82,12 +83,18 @@ class MissingFeaturesDialog : DialogFragment() {
     var dismissListener: DialogInterface.OnDismissListener? = null
     var positiveListener: MaterialDialog.SingleButtonCallback? = null
     var missingFeatures: List<MissingFeature>? = null
+    var readOnly: Boolean = false
 
     fun missingFeatures(missingFeatures: List<MissingFeature>): Builder {
       this.missingFeatures = missingFeatures
       return this
     }
 
+    fun readOnly(readOnly: Boolean): Builder {
+      this.readOnly = readOnly
+      return this
+    }
+
     fun dismissListener(dismissListener: DialogInterface.OnDismissListener): Builder {
       this.dismissListener = dismissListener
       return this
diff --git a/app/src/main/res/layout/fragment_info_core.xml b/app/src/main/res/layout/fragment_info_core.xml
index 1d432236b..45a2928c5 100644
--- a/app/src/main/res/layout/fragment_info_core.xml
+++ b/app/src/main/res/layout/fragment_info_core.xml
@@ -45,6 +45,13 @@
         android:id="@+id/version_date"
         style="@style/Widget.Info.Item.Description"
         tools:text="June 8, 2018" />
+
+      <Button
+        android:id="@+id/missing_features"
+        style="@style/Widget.Button.Borderless.Colored"
+        android:layout_width="wrap_content"
+        android:layout_height="wrap_content"
+        android:text="@string/label_missing_features" />
     </LinearLayout>
 
     <View
-- 
GitLab