add action buttons to bottom of card
This commit is contained in:
parent
d3806ea347
commit
c2003c1576
2 changed files with 94 additions and 29 deletions
|
@ -21,6 +21,7 @@ import androidx.core.content.FileProvider
|
||||||
import androidx.recyclerview.widget.DiffUtil
|
import androidx.recyclerview.widget.DiffUtil
|
||||||
import androidx.recyclerview.widget.ListAdapter
|
import androidx.recyclerview.widget.ListAdapter
|
||||||
import androidx.recyclerview.widget.RecyclerView
|
import androidx.recyclerview.widget.RecyclerView
|
||||||
|
import com.google.android.material.button.MaterialButton
|
||||||
import com.stfalcon.imageviewer.StfalconImageViewer
|
import com.stfalcon.imageviewer.StfalconImageViewer
|
||||||
import io.heckel.ntfy.R
|
import io.heckel.ntfy.R
|
||||||
import io.heckel.ntfy.db.*
|
import io.heckel.ntfy.db.*
|
||||||
|
@ -30,6 +31,7 @@ import io.heckel.ntfy.msg.NotificationService
|
||||||
import io.heckel.ntfy.msg.NotificationService.Companion.ACTION_VIEW
|
import io.heckel.ntfy.msg.NotificationService.Companion.ACTION_VIEW
|
||||||
import io.heckel.ntfy.util.*
|
import io.heckel.ntfy.util.*
|
||||||
import kotlinx.coroutines.*
|
import kotlinx.coroutines.*
|
||||||
|
import java.lang.Integer.min
|
||||||
|
|
||||||
|
|
||||||
class DetailAdapter(private val activity: Activity, private val lifecycleScope: CoroutineScope, private val repository: Repository, private val onClick: (Notification) -> Unit, private val onLongClick: (Notification) -> Unit) :
|
class DetailAdapter(private val activity: Activity, private val lifecycleScope: CoroutineScope, private val repository: Repository, private val onClick: (Notification) -> Unit, private val onLongClick: (Notification) -> Unit) :
|
||||||
|
@ -77,6 +79,11 @@ class DetailAdapter(private val activity: Activity, private val lifecycleScope:
|
||||||
private val attachmentBoxView: View = itemView.findViewById(R.id.detail_item_attachment_file_box)
|
private val attachmentBoxView: View = itemView.findViewById(R.id.detail_item_attachment_file_box)
|
||||||
private val attachmentIconView: ImageView = itemView.findViewById(R.id.detail_item_attachment_file_icon)
|
private val attachmentIconView: ImageView = itemView.findViewById(R.id.detail_item_attachment_file_icon)
|
||||||
private val attachmentInfoView: TextView = itemView.findViewById(R.id.detail_item_attachment_file_info)
|
private val attachmentInfoView: TextView = itemView.findViewById(R.id.detail_item_attachment_file_info)
|
||||||
|
private val actionsWrapperView: View = itemView.findViewById(R.id.detail_item_actions_wrapper)
|
||||||
|
private val action1Button: MaterialButton = itemView.findViewById(R.id.detail_item_action_1)
|
||||||
|
private val action2Button: MaterialButton = itemView.findViewById(R.id.detail_item_action_2)
|
||||||
|
private val action3Button: MaterialButton = itemView.findViewById(R.id.detail_item_action_3)
|
||||||
|
private val actionButtons: List<MaterialButton> = listOf(action1Button, action2Button, action3Button)
|
||||||
|
|
||||||
fun bind(notification: Notification) {
|
fun bind(notification: Notification) {
|
||||||
this.notification = notification
|
this.notification = notification
|
||||||
|
@ -120,6 +127,7 @@ class DetailAdapter(private val activity: Activity, private val lifecycleScope:
|
||||||
renderPriority(context, notification)
|
renderPriority(context, notification)
|
||||||
maybeRenderMenu(context, notification, exists)
|
maybeRenderMenu(context, notification, exists)
|
||||||
maybeRenderAttachment(context, notification, exists)
|
maybeRenderAttachment(context, notification, exists)
|
||||||
|
maybeRenderActions(context, notification)
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun renderPriority(context: Context, notification: Notification) {
|
private fun renderPriority(context: Context, notification: Notification) {
|
||||||
|
@ -168,6 +176,26 @@ class DetailAdapter(private val activity: Activity, private val lifecycleScope:
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private fun maybeRenderActions(context: Context, notification: Notification) {
|
||||||
|
if (notification.actions != null && notification.actions.isNotEmpty()) {
|
||||||
|
actionsWrapperView.visibility = View.VISIBLE
|
||||||
|
val actionsCount = min(notification.actions.size, 3) // per documentation, only 3 actions are available
|
||||||
|
for (i in 0 until actionsCount) {
|
||||||
|
val action = notification.actions[i]
|
||||||
|
val actionButton = actionButtons[i]
|
||||||
|
actionButton.visibility = View.VISIBLE
|
||||||
|
actionButton.text = formatActionLabel(action)
|
||||||
|
actionButton.setOnClickListener { runAction(context, notification, action) }
|
||||||
|
}
|
||||||
|
for (i in actionsCount until 3) {
|
||||||
|
val actionButton = actionButtons[i]
|
||||||
|
actionButton.visibility = View.GONE
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
actionsWrapperView.visibility = View.GONE
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
private fun maybeRenderAttachmentBox(context: Context, notification: Notification, attachment: Attachment, exists: Boolean, image: Boolean) {
|
private fun maybeRenderAttachmentBox(context: Context, notification: Notification, attachment: Attachment, exists: Boolean, image: Boolean) {
|
||||||
if (image) {
|
if (image) {
|
||||||
attachmentBoxView.visibility = View.GONE
|
attachmentBoxView.visibility = View.GONE
|
||||||
|
@ -194,7 +222,6 @@ class DetailAdapter(private val activity: Activity, private val lifecycleScope:
|
||||||
val attachment = notification.attachment // May be null
|
val attachment = notification.attachment // May be null
|
||||||
val hasAttachment = attachment != null
|
val hasAttachment = attachment != null
|
||||||
val hasClickLink = notification.click != ""
|
val hasClickLink = notification.click != ""
|
||||||
val hasUserActions = notification.actions?.isNotEmpty() ?: false
|
|
||||||
val downloadItem = popup.menu.findItem(R.id.detail_item_menu_download)
|
val downloadItem = popup.menu.findItem(R.id.detail_item_menu_download)
|
||||||
val cancelItem = popup.menu.findItem(R.id.detail_item_menu_cancel)
|
val cancelItem = popup.menu.findItem(R.id.detail_item_menu_cancel)
|
||||||
val openItem = popup.menu.findItem(R.id.detail_item_menu_open)
|
val openItem = popup.menu.findItem(R.id.detail_item_menu_open)
|
||||||
|
@ -215,12 +242,6 @@ class DetailAdapter(private val activity: Activity, private val lifecycleScope:
|
||||||
if (hasClickLink) {
|
if (hasClickLink) {
|
||||||
copyContentsItem.setOnMenuItemClickListener { copyContents(context, notification) }
|
copyContentsItem.setOnMenuItemClickListener { copyContents(context, notification) }
|
||||||
}
|
}
|
||||||
if (notification.actions != null && notification.actions.isNotEmpty()) {
|
|
||||||
notification.actions.forEach { action ->
|
|
||||||
val actionItem = popup.menu.add(formatActionLabel(action))
|
|
||||||
actionItem.setOnMenuItemClickListener { runAction(context, notification, action) }
|
|
||||||
}
|
|
||||||
}
|
|
||||||
openItem.isVisible = hasAttachment && exists
|
openItem.isVisible = hasAttachment && exists
|
||||||
downloadItem.isVisible = hasAttachment && !exists && !expired && !inProgress
|
downloadItem.isVisible = hasAttachment && !exists && !expired && !inProgress
|
||||||
deleteItem.isVisible = hasAttachment && exists
|
deleteItem.isVisible = hasAttachment && exists
|
||||||
|
@ -230,7 +251,7 @@ class DetailAdapter(private val activity: Activity, private val lifecycleScope:
|
||||||
copyContentsItem.isVisible = notification.click != ""
|
copyContentsItem.isVisible = notification.click != ""
|
||||||
val noOptions = !openItem.isVisible && !saveFileItem.isVisible && !downloadItem.isVisible
|
val noOptions = !openItem.isVisible && !saveFileItem.isVisible && !downloadItem.isVisible
|
||||||
&& !copyUrlItem.isVisible && !cancelItem.isVisible && !deleteItem.isVisible
|
&& !copyUrlItem.isVisible && !cancelItem.isVisible && !deleteItem.isVisible
|
||||||
&& !copyContentsItem.isVisible && !hasUserActions
|
&& !copyContentsItem.isVisible
|
||||||
if (noOptions) {
|
if (noOptions) {
|
||||||
return null
|
return null
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,24 +1,23 @@
|
||||||
<?xml version="1.0" encoding="utf-8"?>
|
<?xml version="1.0" encoding="utf-8"?>
|
||||||
<androidx.cardview.widget.CardView
|
<androidx.cardview.widget.CardView xmlns:android="http://schemas.android.com/apk/res/android"
|
||||||
xmlns:android="http://schemas.android.com/apk/res/android"
|
xmlns:app="http://schemas.android.com/apk/res-auto"
|
||||||
xmlns:app="http://schemas.android.com/apk/res-auto"
|
style="@style/CardView"
|
||||||
style="@style/CardView"
|
android:id="@+id/detail_item_card"
|
||||||
android:id="@+id/detail_item_card"
|
android:background="?android:attr/selectableItemBackground"
|
||||||
android:background="?android:attr/selectableItemBackground"
|
android:clickable="true"
|
||||||
android:clickable="true"
|
android:focusable="true"
|
||||||
android:focusable="true"
|
android:layout_width="match_parent"
|
||||||
android:layout_width="match_parent"
|
android:layout_height="wrap_content"
|
||||||
android:layout_height="wrap_content"
|
android:layout_marginTop="0dp"
|
||||||
android:layout_marginTop="0dp"
|
android:layout_marginStart="6dp"
|
||||||
android:layout_marginStart="6dp"
|
android:layout_marginEnd="6dp"
|
||||||
android:layout_marginEnd="6dp"
|
android:layout_marginBottom="1dp"
|
||||||
android:layout_marginBottom="1dp"
|
android:padding="3dp"
|
||||||
android:padding="3dp"
|
app:cardCornerRadius="3dp"
|
||||||
app:cardCornerRadius="3dp"
|
app:cardElevation="2dp"
|
||||||
app:cardElevation="2dp"
|
app:cardMaxElevation="2dp"
|
||||||
app:cardMaxElevation="2dp"
|
app:cardPreventCornerOverlap="true"
|
||||||
app:cardPreventCornerOverlap="true"
|
app:cardUseCompatPadding="true">
|
||||||
app:cardUseCompatPadding="true">
|
|
||||||
<androidx.constraintlayout.widget.ConstraintLayout
|
<androidx.constraintlayout.widget.ConstraintLayout
|
||||||
android:id="@+id/detail_item_layout"
|
android:id="@+id/detail_item_layout"
|
||||||
android:layout_width="match_parent"
|
android:layout_width="match_parent"
|
||||||
|
@ -140,7 +139,52 @@
|
||||||
<TextView
|
<TextView
|
||||||
android:layout_width="match_parent"
|
android:layout_width="match_parent"
|
||||||
android:layout_height="5dp" android:id="@+id/detail_item_padding_bottom"
|
android:layout_height="5dp" android:id="@+id/detail_item_padding_bottom"
|
||||||
app:layout_constraintBottom_toBottomOf="parent" app:layout_constraintStart_toStartOf="parent"
|
app:layout_constraintBottom_toTopOf="@+id/detail_item_actions_wrapper" app:layout_constraintStart_toStartOf="parent"
|
||||||
app:layout_constraintTop_toBottomOf="@id/detail_item_attachment_file_box"/>
|
app:layout_constraintTop_toBottomOf="@id/detail_item_attachment_file_box"/>
|
||||||
|
|
||||||
|
<androidx.constraintlayout.widget.ConstraintLayout
|
||||||
|
android:layout_width="match_parent"
|
||||||
|
android:layout_height="wrap_content" app:layout_constraintTop_toBottomOf="@id/detail_item_padding_bottom"
|
||||||
|
android:id="@+id/detail_item_actions_wrapper" app:layout_constraintStart_toStartOf="parent"
|
||||||
|
app:layout_constraintEnd_toEndOf="parent" android:layout_marginStart="10dp" android:layout_marginEnd="10dp"
|
||||||
|
app:layout_constraintBottom_toBottomOf="parent"
|
||||||
|
android:visibility="gone" android:layout_marginTop="2dp"
|
||||||
|
android:padding="4dp">
|
||||||
|
|
||||||
|
<androidx.constraintlayout.helper.widget.Flow
|
||||||
|
android:layout_width="0dp"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
app:layout_constraintEnd_toEndOf="parent"
|
||||||
|
app:constraint_referenced_ids="detail_item_action_1,detail_item_action_2,detail_item_action_3"
|
||||||
|
app:layout_constraintTop_toTopOf="parent"
|
||||||
|
app:flow_wrapMode="chain"
|
||||||
|
app:flow_horizontalStyle="packed"
|
||||||
|
android:id="@+id/detail_item_actions_flow"
|
||||||
|
app:layout_constraintStart_toStartOf="parent"
|
||||||
|
app:flow_horizontalBias="0"
|
||||||
|
app:flow_verticalGap="0dp" app:flow_horizontalGap="0dp"/>
|
||||||
|
|
||||||
|
<com.google.android.material.button.MaterialButton
|
||||||
|
android:id="@+id/detail_item_action_1"
|
||||||
|
style="@style/Widget.MaterialComponents.Button.TextButton"
|
||||||
|
android:layout_width="wrap_content"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:text="View" android:visibility="gone"/>
|
||||||
|
|
||||||
|
<com.google.android.material.button.MaterialButton
|
||||||
|
android:id="@+id/detail_item_action_2"
|
||||||
|
style="@style/Widget.MaterialComponents.Button.TextButton"
|
||||||
|
android:layout_width="wrap_content"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:text="Broadcast" android:visibility="gone"/>
|
||||||
|
|
||||||
|
<com.google.android.material.button.MaterialButton
|
||||||
|
android:id="@+id/detail_item_action_3"
|
||||||
|
style="@style/Widget.MaterialComponents.Button.TextButton"
|
||||||
|
android:layout_width="wrap_content"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:text="HTTP" android:visibility="gone"/>
|
||||||
|
|
||||||
|
</androidx.constraintlayout.widget.ConstraintLayout>
|
||||||
</androidx.constraintlayout.widget.ConstraintLayout>
|
</androidx.constraintlayout.widget.ConstraintLayout>
|
||||||
</androidx.cardview.widget.CardView>
|
</androidx.cardview.widget.CardView>
|
||||||
|
|
Loading…
Reference in a new issue