anytype-kotlin-wild/core-ui/src/main/java/com/anytypeio/anytype/core_ui/widgets/dv/GalleryViewContentWidget.kt

471 lines
23 KiB
Kotlin

package com.anytypeio.anytype.core_ui.widgets.dv
import android.content.Context
import android.graphics.Color
import android.text.TextUtils
import android.util.AttributeSet
import android.util.TypedValue
import android.view.ContextThemeWrapper
import android.view.Gravity
import android.widget.ImageView
import android.widget.LinearLayout
import android.widget.TextView
import androidx.constraintlayout.widget.ConstraintLayout
import androidx.core.content.res.ResourcesCompat
import androidx.core.content.res.use
import androidx.core.view.updateLayoutParams
import com.anytypeio.anytype.core_models.ThemeColor
import com.anytypeio.anytype.core_ui.R
import com.anytypeio.anytype.core_ui.extensions.dark
import com.anytypeio.anytype.core_ui.extensions.light
import com.anytypeio.anytype.core_utils.ext.formatTimestamp
import com.anytypeio.anytype.core_utils.ext.setDrawableColor
import com.anytypeio.anytype.emojifier.Emojifier
import com.anytypeio.anytype.presentation.objects.ObjectIcon
import com.anytypeio.anytype.presentation.relations.model.DefaultObjectRelationValueView
import com.anytypeio.anytype.presentation.sets.model.ObjectView
import com.bumptech.glide.Glide
import timber.log.Timber
class GalleryViewContentWidget @JvmOverloads constructor(
context: Context,
attrs: AttributeSet? = null
) : LinearLayout(context, attrs) {
private var firstItemMargin = 0
private var intervalItemMargin = 0
private var marginAfterIcon = 0
private var marginAfterText = 0
private var defaultBottomMargin = resources.getDimension(R.dimen.dp_4).toInt()
private var defaultTextSize = 0f
private val style = R.style.GalleryViewContentWidgetStyle
private val themeWrapper = ContextThemeWrapper(context, style)
init {
orientation = VERTICAL
if (attrs != null) {
context.obtainStyledAttributes(attrs, R.styleable.GalleryViewContentWidget, 0, 0)
.use { props ->
firstItemMargin =
props.getDimension(R.styleable.GalleryViewContentWidget_firstItemMargin, 0f)
.toInt()
intervalItemMargin = props.getDimension(
R.styleable.GalleryViewContentWidget_itemIntervalMargin,
0f
).toInt()
marginAfterIcon =
props.getDimension(R.styleable.GalleryViewContentWidget_marginAfterIcon, 0f)
.toInt()
marginAfterText =
props.getDimension(R.styleable.GalleryViewContentWidget_marginAfterText, 0f)
.toInt()
defaultTextSize = props.getDimensionPixelSize(
R.styleable.GalleryViewContentWidget_defaultTextSize,
0
).toFloat()
}
}
}
fun setItems(relations: List<DefaultObjectRelationValueView>) {
removeAllViews()
var placeholdersBottom = 0
val size = relations.size
relations.forEachIndexed { index, relation ->
when (relation) {
is DefaultObjectRelationValueView.Empty -> {
placeholdersBottom += 1
}
is DefaultObjectRelationValueView.Text -> {
val view = TextView(themeWrapper).apply {
id = generateViewId()
isSingleLine = true
maxLines = 1
ellipsize = TextUtils.TruncateAt.END
text = relation.text
}
addView(view)
view.updateLayoutParams<LayoutParams> {
marginStart = firstItemMargin
marginEnd = firstItemMargin
bottomMargin = if (index == size - 1) 0 else defaultBottomMargin
}
}
is DefaultObjectRelationValueView.Url -> {
val view = TextView(themeWrapper).apply {
id = generateViewId()
isSingleLine = true
maxLines = 1
ellipsize = TextUtils.TruncateAt.END
text = relation.url
}
addView(view)
view.updateLayoutParams<LayoutParams> {
marginStart = firstItemMargin
marginEnd = firstItemMargin
bottomMargin = if (index == size - 1) 0 else defaultBottomMargin
}
}
is DefaultObjectRelationValueView.Email -> {
val view = TextView(themeWrapper).apply {
id = generateViewId()
isSingleLine = true
maxLines = 1
ellipsize = TextUtils.TruncateAt.END
text = relation.email
}
addView(view)
view.updateLayoutParams<LayoutParams> {
marginStart = firstItemMargin
marginEnd = firstItemMargin
bottomMargin = if (index == size - 1) 0 else defaultBottomMargin
}
}
is DefaultObjectRelationValueView.Number -> {
val view = TextView(themeWrapper).apply {
id = generateViewId()
isSingleLine = true
maxLines = 1
ellipsize = TextUtils.TruncateAt.END
text = relation.number
}
addView(view)
view.updateLayoutParams<LayoutParams> {
marginStart = firstItemMargin
marginEnd = firstItemMargin
bottomMargin = if (index == size - 1) 0 else defaultBottomMargin
}
}
is DefaultObjectRelationValueView.Phone -> {
val view = TextView(themeWrapper).apply {
id = generateViewId()
isSingleLine = true
maxLines = 1
ellipsize = TextUtils.TruncateAt.END
text = relation.phone
}
addView(view)
view.updateLayoutParams<LayoutParams> {
marginStart = firstItemMargin
marginEnd = firstItemMargin
bottomMargin = if (index == size - 1) 0 else defaultBottomMargin
}
}
is DefaultObjectRelationValueView.Date -> {
val view = TextView(themeWrapper).apply {
id = generateViewId()
isSingleLine = true
maxLines = 1
ellipsize = TextUtils.TruncateAt.END
text = relation.timeInMillis?.formatTimestamp(
isMillis = true,
format = relation.dateFormat
)
}
addView(view)
view.updateLayoutParams<LayoutParams> {
marginStart = firstItemMargin
marginEnd = firstItemMargin
bottomMargin = if (index == size - 1) 0 else defaultBottomMargin
}
}
is DefaultObjectRelationValueView.Status -> {
val status = relation.status.firstOrNull()
val color = ThemeColor.values().find { v -> v.code == status?.color }
val defaultTextColor = resources.getColor(R.color.text_primary, null)
val view = TextView(themeWrapper).apply {
id = generateViewId()
text = status?.status
isSingleLine = true
maxLines = 1
ellipsize = TextUtils.TruncateAt.END
if (color != null) {
setTextColor(resources.dark(color, defaultTextColor))
} else {
setTextColor(defaultTextColor)
}
}
addView(view)
view.updateLayoutParams<LayoutParams> {
marginStart = firstItemMargin
marginEnd = firstItemMargin
bottomMargin = if (index == size - 1) 0 else defaultBottomMargin
}
}
is DefaultObjectRelationValueView.Checkbox -> {
val image = ImageView(context)
if (relation.isChecked) {
image.setImageResource(R.drawable.ic_checkbox_gallery_view_checked)
} else {
image.setImageResource(R.drawable.ic_checkbox_gallery_view_unchecked)
}
addView(image)
image.updateLayoutParams<LayoutParams> {
width = resources.getDimension(R.dimen.dp_16).toInt()
height = resources.getDimension(R.dimen.dp_16).toInt()
marginStart = firstItemMargin
bottomMargin = if (index == size - 1) 0 else defaultBottomMargin
}
}
is DefaultObjectRelationValueView.Object -> {
val group = LinearLayout(context).apply {
id = generateViewId()
orientation = HORIZONTAL
}
relation.objects.forEachIndexed { idx, obj ->
if (obj is ObjectView.Default) {
when (val icon = obj.icon) {
is ObjectIcon.None -> {
// Do nothing
}
is ObjectIcon.Basic.Avatar -> {
// Do nothing
}
is ObjectIcon.Basic.Emoji -> {
try {
val image = ImageView(context)
group.addView(image)
image.updateLayoutParams<LayoutParams> {
width = resources.getDimension(R.dimen.dp_16).toInt()
height = resources.getDimension(R.dimen.dp_16).toInt()
gravity = Gravity.CENTER_VERTICAL
marginStart = if (idx == 0) {
firstItemMargin
} else {
intervalItemMargin
}
marginEnd = marginAfterIcon
}
Glide
.with(this)
.load(Emojifier.uri(icon.unicode))
.into(image)
} catch (e: Throwable) {
Timber.w(
e,
"Error while setting emoji icon for: ${icon.unicode}"
)
}
}
is ObjectIcon.Basic.Image -> {
val image = ImageView(context)
group.addView(image)
image.updateLayoutParams<LayoutParams> {
width = resources.getDimension(R.dimen.dp_16).toInt()
height = resources.getDimension(R.dimen.dp_16).toInt()
gravity = Gravity.CENTER_VERTICAL
marginStart = if (idx == 0) {
firstItemMargin
} else {
0
}
marginEnd = marginAfterIcon
}
Glide
.with(this)
.load(icon.hash)
.centerCrop()
.into(image)
}
is ObjectIcon.Profile.Avatar -> {
val avatar = TextView(themeWrapper).apply {
gravity = Gravity.CENTER
isAllCaps = true
setBackgroundResource(R.drawable.circle_default_avatar_background)
setTextSize(
TypedValue.COMPLEX_UNIT_PX,
resources.getDimension(R.dimen.defaultGalleryViewAvatarTextSize)
)
typeface =
ResourcesCompat.getFont(context, R.font.inter_medium)
setTextColor(Color.WHITE)
text = if (icon.name.isNotEmpty())
icon.name.first().toString()
else
resources.getText(R.string.u)
}
group.addView(avatar)
avatar.updateLayoutParams<LayoutParams> {
width = resources.getDimension(R.dimen.dp_16).toInt()
height = resources.getDimension(R.dimen.dp_16).toInt()
marginStart = if (idx == 0) {
firstItemMargin
} else {
0
}
marginEnd = marginAfterIcon
}
}
is ObjectIcon.Profile.Image -> {
val image = ImageView(context)
group.addView(image)
image.updateLayoutParams<LayoutParams> {
width = resources.getDimension(R.dimen.dp_16).toInt()
height = resources.getDimension(R.dimen.dp_16).toInt()
gravity = Gravity.CENTER_VERTICAL
marginStart = if (idx == 0) {
firstItemMargin
} else {
0
}
marginEnd = marginAfterIcon
}
Glide
.with(this)
.load(icon.hash)
.circleCrop()
.into(image)
}
is ObjectIcon.Task -> {
val image = ImageView(context).apply {
if (icon.isChecked) {
setImageResource(R.drawable.ic_gallery_view_task_checked)
} else {
setImageResource(R.drawable.ic_gallery_view_task_unchecked)
}
}
group.addView(image)
image.updateLayoutParams<LayoutParams> {
width = resources.getDimension(R.dimen.dp_16).toInt()
height = resources.getDimension(R.dimen.dp_16).toInt()
gravity = Gravity.CENTER_VERTICAL
marginStart = if (idx == 0) {
firstItemMargin
} else {
0
}
marginEnd = marginAfterIcon
}
}
else -> {}
}
val noIcon =
obj.icon == ObjectIcon.None || obj.icon is ObjectIcon.Basic.Avatar
val view = TextView(themeWrapper).apply {
id = generateViewId()
isSingleLine = true
maxLines = 1
ellipsize = TextUtils.TruncateAt.END
setHint(R.string.untitled)
text = obj.name
}
group.addView(view)
view.updateLayoutParams<LayoutParams> {
marginStart = if (idx == 0 && noIcon) firstItemMargin else 0
marginEnd = marginAfterText
}
}
}
addView(group)
group.updateLayoutParams<LayoutParams> {
bottomMargin = if (index == size - 1) 0 else defaultBottomMargin
marginEnd = firstItemMargin
}
}
is DefaultObjectRelationValueView.Tag -> {
val group = LinearLayout(context).apply {
id = generateViewId()
orientation = HORIZONTAL
}
relation.tags.forEachIndexed { idx, tag ->
val color = ThemeColor.values().find { v -> v.code == tag.color }
val defaultTextColor = resources.getColor(R.color.text_primary, null)
val defaultBackground = resources.getColor(R.color.shape_primary, null)
val view = TextView(themeWrapper).apply {
id = generateViewId()
isSingleLine = true
maxLines = 1
ellipsize = TextUtils.TruncateAt.END
text = tag.tag
if (color != null) {
setTextColor(resources.dark(color, defaultTextColor))
setBackgroundResource(R.drawable.rect_dv_cell_tag_item)
background.setDrawableColor(
resources.light(
color,
defaultBackground
)
)
} else {
setTextColor(defaultTextColor)
setBackgroundResource(R.drawable.rect_dv_cell_tag_item)
background.setDrawableColor(defaultBackground)
}
}
group.addView(view)
view.updateLayoutParams<LayoutParams> {
marginStart = if (idx == 0) {
firstItemMargin
} else {
intervalItemMargin
}
}
}
addView(group)
group.updateLayoutParams<LayoutParams> {
bottomMargin = if (index == size - 1) 0 else defaultBottomMargin
marginEnd = firstItemMargin
}
}
is DefaultObjectRelationValueView.File -> {
val group = LinearLayout(context).apply {
id = generateViewId()
orientation = HORIZONTAL
}
relation.files.forEachIndexed { idx, file ->
val filename = file.name + "." + file.ext
val view = TextView(themeWrapper).apply {
id = generateViewId()
isSingleLine = true
maxLines = 1
ellipsize = TextUtils.TruncateAt.END
text = filename
setHint(R.string.untitled)
}
group.addView(view)
view.updateLayoutParams<LayoutParams> {
marginStart = if (idx == 0) {
firstItemMargin
} else {
intervalItemMargin
}
}
}
addView(group)
group.updateLayoutParams<LayoutParams> {
bottomMargin = if (index == size - 1) 0 else defaultBottomMargin
marginEnd = firstItemMargin
}
}
else -> {
val view = TextView(themeWrapper).apply {
id = generateViewId()
text = relation::class.java.simpleName
}
addView(view)
view.updateLayoutParams<LayoutParams> {
marginStart = firstItemMargin
bottomMargin = if (index == size - 1) 0 else defaultBottomMargin
}
}
}
}
val cardBottomMargin = resources.getDimension(R.dimen.dp_16).toInt()
if (placeholdersBottom > 0) {
val margin = resources.getDimension(R.dimen.dp_20)
.toInt() * placeholdersBottom + cardBottomMargin
this.updateLayoutParams<ConstraintLayout.LayoutParams> {
bottomMargin = margin
}
} else {
this.updateLayoutParams<ConstraintLayout.LayoutParams> {
bottomMargin = cardBottomMargin
}
}
}
}