diff --git a/app/src/main/kotlin/org/koitharu/kotatsu/core/ui/widgets/TipView.kt b/app/src/main/kotlin/org/koitharu/kotatsu/core/ui/widgets/TipView.kt
new file mode 100644
index 000000000..a481f156b
--- /dev/null
+++ b/app/src/main/kotlin/org/koitharu/kotatsu/core/ui/widgets/TipView.kt
@@ -0,0 +1,135 @@
+package org.koitharu.kotatsu.core.ui.widgets
+
+import android.content.Context
+import android.graphics.Outline
+import android.graphics.Rect
+import android.graphics.RectF
+import android.graphics.drawable.Drawable
+import android.util.AttributeSet
+import android.view.LayoutInflater
+import android.view.View
+import android.view.ViewOutlineProvider
+import android.widget.LinearLayout
+import androidx.annotation.DrawableRes
+import androidx.annotation.StringRes
+import androidx.core.content.ContextCompat
+import androidx.core.content.withStyledAttributes
+import androidx.core.view.setPadding
+import com.google.android.material.shape.MaterialShapeDrawable
+import com.google.android.material.shape.ShapeAppearanceModel
+import org.koitharu.kotatsu.R
+import org.koitharu.kotatsu.core.util.ext.drawableStart
+import org.koitharu.kotatsu.core.util.ext.getDrawableCompat
+import org.koitharu.kotatsu.core.util.ext.getThemeColorStateList
+import org.koitharu.kotatsu.core.util.ext.setTextAndVisible
+import org.koitharu.kotatsu.core.util.ext.textAndVisible
+import org.koitharu.kotatsu.databinding.ViewTipBinding
+import com.google.android.material.R as materialR
+
+class TipView @JvmOverloads constructor(
+ context: Context,
+ attrs: AttributeSet? = null,
+ defStyleAttr: Int = R.attr.tipViewStyle,
+) : LinearLayout(context, attrs, defStyleAttr), View.OnClickListener {
+
+ private val binding = ViewTipBinding.inflate(LayoutInflater.from(context), this)
+
+ var title: CharSequence?
+ get() = binding.textViewTitle.text
+ set(value) {
+ binding.textViewTitle.text = value
+ }
+
+ var text: CharSequence?
+ get() = binding.textViewBody.text
+ set(value) {
+ binding.textViewBody.text = value
+ }
+
+ var icon: Drawable?
+ get() = binding.textViewTitle.drawableStart
+ set(value) {
+ binding.textViewTitle.drawableStart = value
+ }
+
+ var primaryButtonText: CharSequence?
+ get() = binding.buttonPrimary.textAndVisible
+ set(value) {
+ binding.buttonPrimary.textAndVisible = value
+ }
+
+ var secondaryButtonText: CharSequence?
+ get() = binding.buttonSecondary.textAndVisible
+ set(value) {
+ binding.buttonSecondary.textAndVisible = value
+ }
+
+ var onButtonClickListener: OnButtonClickListener? = null
+
+ init {
+ orientation = VERTICAL
+ setPadding(context.resources.getDimensionPixelOffset(R.dimen.margin_normal))
+ context.withStyledAttributes(attrs, R.styleable.TipView, defStyleAttr) {
+ title = getText(R.styleable.TipView_title)
+ text = getText(R.styleable.TipView_android_text)
+ icon = getDrawableCompat(context, R.styleable.TipView_icon)
+ primaryButtonText = getString(R.styleable.TipView_primaryButtonText)
+ secondaryButtonText = getString(R.styleable.TipView_secondaryButtonText)
+ val shapeAppearanceModel = ShapeAppearanceModel.builder(context, attrs, defStyleAttr, 0).build()
+ background = MaterialShapeDrawable(shapeAppearanceModel).also {
+ it.fillColor = getColorStateList(R.styleable.TipView_cardBackgroundColor)
+ ?: context.getThemeColorStateList(materialR.attr.colorBackgroundFloating)
+ it.strokeWidth = getDimension(R.styleable.TipView_strokeWidth, 0f)
+ it.strokeColor = getColorStateList(R.styleable.TipView_strokeColor)
+ it.elevation = getDimension(R.styleable.TipView_elevation, 0f)
+ }
+ outlineProvider = OutlineProvider(shapeAppearanceModel)
+ }
+ }
+
+ override fun onClick(v: View) {
+ when (v.id) {
+ R.id.button_primary -> onButtonClickListener?.onPrimaryButtonClick(this)
+ R.id.button_secondary -> onButtonClickListener?.onSecondaryButtonClick(this)
+ }
+ }
+
+ fun setTitle(@StringRes resId: Int) {
+ binding.textViewTitle.setText(resId)
+ }
+
+ fun setText(@StringRes resId: Int) {
+ binding.textViewBody.setText(resId)
+ }
+
+ fun setPrimaryButtonText(@StringRes resId: Int) {
+ binding.buttonPrimary.setTextAndVisible(resId)
+ }
+
+ fun setSecondaryButtonText(@StringRes resId: Int) {
+ binding.buttonSecondary.setTextAndVisible(resId)
+ }
+
+ fun setIcon(@DrawableRes resId: Int) {
+ icon = ContextCompat.getDrawable(context, resId)
+ }
+
+ interface OnButtonClickListener {
+
+ fun onPrimaryButtonClick(tipView: TipView)
+
+ fun onSecondaryButtonClick(tipView: TipView)
+ }
+
+ private class OutlineProvider(
+ shapeAppearanceModel: ShapeAppearanceModel,
+ ) : ViewOutlineProvider() {
+
+ private val shapeDrawable = MaterialShapeDrawable(shapeAppearanceModel)
+ override fun getOutline(view: View, outline: Outline) {
+ shapeDrawable.setBounds(0, 0, view.width, view.height)
+ shapeDrawable.getOutline(outline)
+ }
+ }
+
+}
diff --git a/app/src/main/kotlin/org/koitharu/kotatsu/core/util/ext/Theme.kt b/app/src/main/kotlin/org/koitharu/kotatsu/core/util/ext/Theme.kt
index dae151af2..4ce515d9b 100644
--- a/app/src/main/kotlin/org/koitharu/kotatsu/core/util/ext/Theme.kt
+++ b/app/src/main/kotlin/org/koitharu/kotatsu/core/util/ext/Theme.kt
@@ -1,11 +1,16 @@
package org.koitharu.kotatsu.core.util.ext
import android.content.Context
+import android.content.res.TypedArray
import android.graphics.Color
+import android.graphics.drawable.Drawable
import androidx.annotation.AttrRes
import androidx.annotation.ColorInt
import androidx.annotation.FloatRange
import androidx.annotation.Px
+import androidx.core.content.ContextCompat
+import androidx.core.content.res.ResourcesCompat
+import androidx.core.content.res.TypedArrayUtils
import androidx.core.content.res.use
import androidx.core.graphics.ColorUtils
@@ -60,3 +65,8 @@ fun Context.getThemeColorStateList(
) = obtainStyledAttributes(intArrayOf(resId)).use {
it.getColorStateList(0)
}
+
+fun TypedArray.getDrawableCompat(context: Context, index: Int): Drawable? {
+ val resId = getResourceId(index, 0)
+ return if (resId != 0) ContextCompat.getDrawable(context, resId) else null
+}
diff --git a/app/src/main/res/layout/item_tip2.xml b/app/src/main/res/layout/item_tip2.xml
new file mode 100644
index 000000000..93add6a92
--- /dev/null
+++ b/app/src/main/res/layout/item_tip2.xml
@@ -0,0 +1,14 @@
+
+
diff --git a/app/src/main/res/layout/view_tip.xml b/app/src/main/res/layout/view_tip.xml
new file mode 100644
index 000000000..dcbbe184a
--- /dev/null
+++ b/app/src/main/res/layout/view_tip.xml
@@ -0,0 +1,64 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/app/src/main/res/values/attrs.xml b/app/src/main/res/values/attrs.xml
index ded307bcd..a17dbf64f 100644
--- a/app/src/main/res/values/attrs.xml
+++ b/app/src/main/res/values/attrs.xml
@@ -7,12 +7,7 @@
-
-
-
-
-
-
+
@@ -112,4 +107,18 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+