1
0
Fork 0
mirror of https://github.com/anyproto/anytype-kotlin.git synced 2025-06-11 02:13:30 +09:00

Refact/list holders in separate classes (#706)

This commit is contained in:
Evgenii Kozlov 2020-08-19 17:22:12 +02:00 committed by GitHub
parent 48178cff20
commit fb9e6cbd29
Signed by: github
GPG key ID: 4AEE18F83AFDEB23
11 changed files with 640 additions and 584 deletions

View file

@ -7,8 +7,8 @@ import android.widget.ImageView
import android.widget.TextView
import com.agileburo.anytype.R
import com.agileburo.anytype.core_ui.common.toSpannable
import com.agileburo.anytype.core_ui.features.editor.holders.Toggle
import com.agileburo.anytype.core_ui.features.page.BlockView
import com.agileburo.anytype.core_ui.features.page.BlockViewHolder
class ToggleBlockActionToolbar : BlockActionToolbar() {
@ -40,8 +40,8 @@ class ToggleBlockActionToolbar : BlockActionToolbar() {
)
view.findViewById<ImageView>(R.id.toggle).apply {
rotation =
if (block.toggled) BlockViewHolder.Toggle.EXPANDED_ROTATION
else BlockViewHolder.Toggle.COLLAPSED_ROTATION
if (block.toggled) Toggle.EXPANDED_ROTATION
else Toggle.COLLAPSED_ROTATION
}
setConstraints()
}

View file

@ -0,0 +1,132 @@
package com.agileburo.anytype.core_ui.features.editor.holders
import android.text.Editable
import android.view.View
import androidx.core.view.updateLayoutParams
import com.agileburo.anytype.core_ui.R
import com.agileburo.anytype.core_ui.common.Markup
import com.agileburo.anytype.core_ui.common.ThemeColor
import com.agileburo.anytype.core_ui.common.isLinksPresent
import com.agileburo.anytype.core_ui.extensions.color
import com.agileburo.anytype.core_ui.extensions.tint
import com.agileburo.anytype.core_ui.features.page.*
import com.agileburo.anytype.core_ui.menu.ContextMenuType
import com.agileburo.anytype.core_ui.tools.DefaultTextWatcher
import com.agileburo.anytype.core_ui.widgets.text.EditorLongClickListener
import com.agileburo.anytype.core_ui.widgets.text.TextInputWidget
import com.agileburo.anytype.core_utils.ext.dimen
import kotlinx.android.synthetic.main.item_block_bulleted.view.*
class Bulleted(
view: View,
onMarkupActionClicked: (Markup.Type, IntRange) -> Unit
) : BlockViewHolder(view), TextHolder, BlockViewHolder.IndentableHolder, SupportNesting {
val indent = itemView.bulletIndent
private val bullet = itemView.bullet
private val container = itemView.bulletBlockContainer
override val content: TextInputWidget = itemView.bulletedListContent
override val root: View = itemView
init {
setup(onMarkupActionClicked, ContextMenuType.TEXT)
}
fun bind(
item: BlockView.Bulleted,
onTextChanged: (String, Editable) -> Unit,
onSelectionChanged: (String, IntRange) -> Unit,
onFocusChanged: (String, Boolean) -> Unit,
clicked: (ListenerType) -> Unit
) {
indentize(item)
if (item.mode == BlockView.Mode.READ) {
enableReadOnlyMode()
select(item)
setBlockText(text = item.text, markup = item, clicked = clicked)
if (item.color != null)
setTextColor(item.color)
else
setTextColor(content.context.color(R.color.black))
} else {
enableEditMode()
select(item)
content.setOnLongClickListener(
EditorLongClickListener(
t = item.id,
click = { onBlockLongClick(root, it, clicked) }
)
)
content.clearTextWatchers()
if (item.marks.isLinksPresent()) {
content.setLinksClickable()
}
setBlockText(text = item.text, markup = item, clicked = clicked)
if (item.color != null) {
setTextColor(item.color)
} else {
setTextColor(content.context.color(R.color.black))
}
if (item.isFocused) setCursor(item)
setFocus(item)
content.addTextChangedListener(
DefaultTextWatcher { text ->
onTextChanged(item.id, text)
}
)
content.setOnFocusChangeListener { _, hasFocus ->
onFocusChanged(item.id, hasFocus)
}
content.selectionWatcher = {
onSelectionChanged(item.id, it)
}
}
}
override fun getMentionImageSizeAndPadding(): Pair<Int, Int> = with(itemView) {
Pair(
first = resources.getDimensionPixelSize(R.dimen.mention_span_image_size_default),
second = resources.getDimensionPixelSize(R.dimen.mention_span_image_padding_default)
)
}
override fun setTextColor(color: String) {
super.setTextColor(color)
bullet.setColorFilter(
ThemeColor.values().first { value ->
value.title == color
}.text
)
}
override fun setTextColor(color: Int) {
super.setTextColor(color)
bullet.tint(content.context.color(R.color.black))
}
override fun indentize(item: BlockView.Indentable) {
indent.updateLayoutParams { width = item.indent * dimen(R.dimen.indent) }
}
override fun select(item: BlockView.Selectable) {
container.isSelected = item.isSelected
}
}

View file

@ -0,0 +1,150 @@
package com.agileburo.anytype.core_ui.features.editor.holders
import android.content.Context
import android.text.Editable
import android.view.View
import android.widget.ImageView
import android.widget.TextView
import androidx.core.view.updatePadding
import com.agileburo.anytype.core_ui.R
import com.agileburo.anytype.core_ui.common.Markup
import com.agileburo.anytype.core_ui.common.isLinksPresent
import com.agileburo.anytype.core_ui.extensions.color
import com.agileburo.anytype.core_ui.features.page.*
import com.agileburo.anytype.core_ui.menu.ContextMenuType
import com.agileburo.anytype.core_ui.tools.DefaultTextWatcher
import com.agileburo.anytype.core_ui.widgets.text.EditorLongClickListener
import com.agileburo.anytype.core_ui.widgets.text.TextInputWidget
import com.agileburo.anytype.core_utils.ext.dimen
import kotlinx.android.synthetic.main.item_block_checkbox.view.*
class Checkbox(
view: View,
onMarkupActionClicked: (Markup.Type, IntRange) -> Unit
) : BlockViewHolder(view), TextHolder, BlockViewHolder.IndentableHolder, SupportNesting {
var mode = BlockView.Mode.EDIT
val checkbox: ImageView = itemView.checkboxIcon
private val container = itemView.checkboxBlockContentContainer
override val content: TextInputWidget = itemView.checkboxContent
override val root: View = itemView
init {
setup(onMarkupActionClicked, ContextMenuType.TEXT)
}
fun bind(
item: BlockView.Checkbox,
onTextChanged: (String, Editable) -> Unit,
onCheckboxClicked: (String) -> Unit,
onSelectionChanged: (String, IntRange) -> Unit,
onFocusChanged: (String, Boolean) -> Unit,
clicked: (ListenerType) -> Unit
) {
indentize(item)
if (item.mode == BlockView.Mode.READ) {
enableReadOnlyMode()
select(item)
updateTextColor(
context = itemView.context,
view = content,
isSelected = checkbox.isActivated
)
checkbox.isActivated = item.isChecked
setBlockText(text = item.text, markup = item, clicked = clicked)
} else {
enableEditMode()
select(item)
content.setOnLongClickListener(
EditorLongClickListener(
t = item.id,
click = { onBlockLongClick(root, it, clicked) }
)
)
content.clearTextWatchers()
checkbox.isActivated = item.isChecked
updateTextColor(
context = itemView.context,
view = content,
isSelected = checkbox.isActivated
)
if (item.marks.isLinksPresent()) {
content.setLinksClickable()
}
setBlockText(text = item.text, markup = item, clicked = clicked)
if (item.isFocused) setCursor(item)
setFocus(item)
checkbox.setOnClickListener {
if (mode == BlockView.Mode.EDIT) {
checkbox.isActivated = !checkbox.isActivated
updateTextColor(
context = itemView.context,
view = content,
isSelected = checkbox.isActivated
)
onCheckboxClicked(item.id)
}
}
content.setOnFocusChangeListener { _, hasFocus ->
onFocusChanged(item.id, hasFocus)
}
content.addTextChangedListener(
DefaultTextWatcher { text ->
onTextChanged(item.id, text)
}
)
content.selectionWatcher = {
onSelectionChanged(item.id, it)
}
}
}
override fun getMentionImageSizeAndPadding(): Pair<Int, Int> = with(itemView) {
Pair(
first = resources.getDimensionPixelSize(R.dimen.mention_span_image_size_default),
second = resources.getDimensionPixelSize(R.dimen.mention_span_image_padding_default)
)
}
override fun indentize(item: BlockView.Indentable) {
checkbox.updatePadding(left = item.indent * dimen(R.dimen.indent))
}
override fun enableEditMode() {
super.enableEditMode()
mode = BlockView.Mode.EDIT
}
override fun enableReadOnlyMode() {
super.enableReadOnlyMode()
mode = BlockView.Mode.READ
}
override fun select(item: BlockView.Selectable) {
container.isSelected = item.isSelected
}
private fun updateTextColor(context: Context, view: TextView, isSelected: Boolean) =
view.setTextColor(
context.color(
if (isSelected) R.color.checkbox_state_checked else R.color.black
)
)
}

View file

@ -0,0 +1,149 @@
package com.agileburo.anytype.core_ui.features.editor.holders
import android.text.Editable
import android.view.Gravity
import android.view.View
import android.widget.LinearLayout
import androidx.core.view.updateLayoutParams
import com.agileburo.anytype.core_ui.R
import com.agileburo.anytype.core_ui.common.Markup
import com.agileburo.anytype.core_ui.common.isLinksPresent
import com.agileburo.anytype.core_ui.extensions.color
import com.agileburo.anytype.core_ui.features.page.*
import com.agileburo.anytype.core_ui.menu.ContextMenuType
import com.agileburo.anytype.core_ui.tools.DefaultTextWatcher
import com.agileburo.anytype.core_ui.widgets.text.EditorLongClickListener
import com.agileburo.anytype.core_ui.widgets.text.TextInputWidget
import com.agileburo.anytype.core_utils.ext.addDot
import com.agileburo.anytype.core_utils.ext.dimen
import kotlinx.android.synthetic.main.item_block_numbered.view.*
class Numbered(
view: View,
onMarkupActionClicked: (Markup.Type, IntRange) -> Unit
) : BlockViewHolder(view), TextHolder, BlockViewHolder.IndentableHolder, SupportNesting {
private val container = itemView.numberedBlockContentContainer
val number = itemView.number
override val content: TextInputWidget = itemView.numberedListContent
override val root: View = itemView
init {
setup(onMarkupActionClicked, ContextMenuType.TEXT)
}
fun bind(
item: BlockView.Numbered,
onTextChanged: (String, Editable) -> Unit,
onSelectionChanged: (String, IntRange) -> Unit,
onFocusChanged: (String, Boolean) -> Unit,
clicked: (ListenerType) -> Unit
) {
indentize(item)
if (item.mode == BlockView.Mode.READ) {
enableReadOnlyMode()
select(item)
number.gravity = when (item.number) {
in 1..19 -> Gravity.CENTER_HORIZONTAL
else -> Gravity.START
}
number.text = item.number.addDot()
setBlockText(text = item.text, markup = item, clicked = clicked)
if (item.color != null)
setTextColor(item.color)
else
setTextColor(content.context.color(R.color.black))
} else {
enableEditMode()
select(item)
content.setOnLongClickListener(
EditorLongClickListener(
t = item.id,
click = { onBlockLongClick(root, it, clicked) }
)
)
content.clearTextWatchers()
indentize(item)
number.gravity = when (item.number) {
in 1..19 -> Gravity.CENTER_HORIZONTAL
else -> Gravity.START
}
number.text = item.number.addDot()
if (item.marks.isLinksPresent()) {
content.setLinksClickable()
}
setBlockText(text = item.text, markup = item, clicked = clicked)
if (item.color != null)
setTextColor(item.color)
else
setTextColor(content.context.color(R.color.black))
if (item.isFocused) setCursor(item)
setFocus(item)
content.addTextChangedListener(
DefaultTextWatcher { text ->
onTextChanged(item.id, text)
}
)
content.setOnFocusChangeListener { _, hasFocus ->
onFocusChanged(item.id, hasFocus)
}
content.selectionWatcher = {
onSelectionChanged(item.id, it)
}
}
}
override fun getMentionImageSizeAndPadding(): Pair<Int, Int> = with(itemView) {
Pair(
first = resources.getDimensionPixelSize(R.dimen.mention_span_image_size_default),
second = resources.getDimensionPixelSize(R.dimen.mention_span_image_padding_default)
)
}
override fun processChangePayload(
payloads: List<BlockViewDiffUtil.Payload>,
item: BlockView,
onTextChanged: (String, Editable) -> Unit,
onSelectionChanged: (String, IntRange) -> Unit,
clicked: (ListenerType) -> Unit
) {
super.processChangePayload(payloads, item, onTextChanged, onSelectionChanged, clicked)
payloads.forEach { payload ->
if (payload.changes.contains(BlockViewDiffUtil.NUMBER_CHANGED))
number.text = "${(item as BlockView.Numbered).number}"
}
}
override fun indentize(item: BlockView.Indentable) {
number.updateLayoutParams<LinearLayout.LayoutParams> {
setMargins(
item.indent * dimen(R.dimen.indent),
0,
0,
0
)
}
}
override fun select(item: BlockView.Selectable) {
container.isSelected = item.isSelected
}
}

View file

@ -0,0 +1,170 @@
package com.agileburo.anytype.core_ui.features.editor.holders
import android.text.Editable
import android.view.View
import androidx.core.view.isVisible
import com.agileburo.anytype.core_ui.R
import com.agileburo.anytype.core_ui.common.Markup
import com.agileburo.anytype.core_ui.common.isLinksPresent
import com.agileburo.anytype.core_ui.extensions.color
import com.agileburo.anytype.core_ui.features.page.*
import com.agileburo.anytype.core_ui.menu.ContextMenuType
import com.agileburo.anytype.core_ui.widgets.text.EditorLongClickListener
import com.agileburo.anytype.core_ui.widgets.text.TextInputWidget
import com.agileburo.anytype.core_utils.ext.dimen
import kotlinx.android.synthetic.main.item_block_toggle.view.*
class Toggle(
view: View,
onMarkupActionClicked: (Markup.Type, IntRange) -> Unit
) : BlockViewHolder(view), TextHolder, BlockViewHolder.IndentableHolder, SupportNesting {
private var mode = BlockView.Mode.EDIT
val toggle = itemView.toggle
private val line = itemView.guideline
private val placeholder = itemView.togglePlaceholder
private val container = itemView.toolbarBlockContentContainer
override val content: TextInputWidget = itemView.toggleContent
override val root: View = itemView
init {
setup(onMarkupActionClicked, ContextMenuType.TEXT)
}
fun bind(
item: BlockView.Toggle,
onTextChanged: (String, Editable) -> Unit,
onSelectionChanged: (String, IntRange) -> Unit,
onFocusChanged: (String, Boolean) -> Unit,
onToggleClicked: (String) -> Unit,
onTogglePlaceholderClicked: (String) -> Unit,
clicked: (ListenerType) -> Unit
) {
indentize(item)
if (item.mode == BlockView.Mode.READ) {
enableReadOnlyMode()
select(item)
setBlockText(text = item.text, markup = item, clicked = clicked)
if (item.color != null)
setTextColor(item.color)
else
setTextColor(content.context.color(R.color.black))
placeholder.isVisible = false
toggle.apply {
rotation = if (item.toggled) EXPANDED_ROTATION else COLLAPSED_ROTATION
}
} else {
enableEditMode()
select(item)
content.setOnLongClickListener(
EditorLongClickListener(
t = item.id,
click = { onBlockLongClick(root, it, clicked) }
)
)
if (item.marks.isLinksPresent()) {
content.setLinksClickable()
}
content.clearTextWatchers()
setBlockText(text = item.text, markup = item, clicked = clicked)
if (item.color != null) {
setTextColor(item.color)
} else {
setTextColor(content.context.color(R.color.black))
}
if (item.isFocused) setCursor(item)
setFocus(item)
setupTextWatcher(onTextChanged, item)
content.setOnFocusChangeListener { _, focused ->
item.isFocused = focused
onFocusChanged(item.id, focused)
}
content.selectionWatcher = {
onSelectionChanged(item.id, it)
}
placeholder.apply {
isVisible = item.isEmpty && item.toggled
setOnClickListener { onTogglePlaceholderClicked(item.id) }
}
}
toggle.apply {
rotation = if (item.toggled) EXPANDED_ROTATION else COLLAPSED_ROTATION
setOnClickListener {
if (mode == BlockView.Mode.EDIT) onToggleClicked(item.id)
}
}
}
override fun getMentionImageSizeAndPadding(): Pair<Int, Int> = with(itemView) {
Pair(
first = resources.getDimensionPixelSize(R.dimen.mention_span_image_size_default),
second = resources.getDimensionPixelSize(R.dimen.mention_span_image_padding_default)
)
}
override fun indentize(item: BlockView.Indentable) {
line.setGuidelineBegin(item.indent * dimen(R.dimen.indent))
}
override fun select(item: BlockView.Selectable) {
container.isSelected = item.isSelected
}
override fun enableReadOnlyMode() {
super.enableReadOnlyMode()
mode = BlockView.Mode.READ
}
override fun enableEditMode() {
super.enableEditMode()
mode = BlockView.Mode.EDIT
}
override fun processChangePayload(
payloads: List<BlockViewDiffUtil.Payload>,
item: BlockView,
onTextChanged: (String, Editable) -> Unit,
onSelectionChanged: (String, IntRange) -> Unit,
clicked: (ListenerType) -> Unit
) {
check(item is BlockView.Toggle) { "Expected a toggle block, but was: $item" }
super.processChangePayload(payloads, item, onTextChanged, onSelectionChanged, clicked)
payloads.forEach { payload ->
if (payload.changes.contains(BlockViewDiffUtil.TOGGLE_EMPTY_STATE_CHANGED))
placeholder.isVisible = item.isEmpty
}
}
companion object {
/**
* Rotation value for a toggle icon for expanded state.
*/
const val EXPANDED_ROTATION = 90f
/**
* Rotation value for a toggle icon for collapsed state.
*/
const val COLLAPSED_ROTATION = 0f
}
}

View file

@ -158,7 +158,7 @@ class BlockAdapter(
)
}
HOLDER_CHECKBOX -> {
BlockViewHolder.Checkbox(
Checkbox(
view = inflater.inflate(
R.layout.item_block_checkbox,
parent,
@ -168,7 +168,7 @@ class BlockAdapter(
)
}
HOLDER_BULLET -> {
BlockViewHolder.Bulleted(
Bulleted(
view = inflater.inflate(
R.layout.item_block_bulleted,
parent,
@ -178,7 +178,7 @@ class BlockAdapter(
)
}
HOLDER_NUMBERED -> {
BlockViewHolder.Numbered(
Numbered(
view = inflater.inflate(
R.layout.item_block_numbered,
parent,
@ -188,7 +188,7 @@ class BlockAdapter(
)
}
HOLDER_TOGGLE -> {
BlockViewHolder.Toggle(
Toggle(
view = inflater.inflate(
R.layout.item_block_toggle,
parent,
@ -414,7 +414,7 @@ class BlockAdapter(
clicked = onClickListener
)
}
is BlockViewHolder.Bulleted -> {
is Bulleted -> {
holder.processChangePayload(
payloads = payloads.typeOf(),
item = blocks[position],
@ -423,7 +423,7 @@ class BlockAdapter(
clicked = onClickListener
)
}
is BlockViewHolder.Checkbox -> {
is Checkbox -> {
holder.processChangePayload(
payloads = payloads.typeOf(),
item = blocks[position],
@ -444,7 +444,7 @@ class BlockAdapter(
item = blocks[position] as BlockView.Title.Profile
)
}
is BlockViewHolder.Numbered -> {
is Numbered -> {
holder.processChangePayload(
payloads = payloads.typeOf(),
item = blocks[position],
@ -480,7 +480,7 @@ class BlockAdapter(
clicked = onClickListener
)
}
is BlockViewHolder.Toggle -> {
is Toggle -> {
holder.processChangePayload(
payloads = payloads.typeOf(),
item = blocks[position],
@ -673,7 +673,7 @@ class BlockAdapter(
clicked = onClickListener
)
}
is BlockViewHolder.Checkbox -> {
is Checkbox -> {
holder.bind(
item = blocks[position] as BlockView.Checkbox,
onTextChanged = onTextChanged,
@ -683,7 +683,7 @@ class BlockAdapter(
clicked = onClickListener
)
}
is BlockViewHolder.Bulleted -> {
is Bulleted -> {
holder.bind(
item = blocks[position] as BlockView.Bulleted,
onTextChanged = onTextChanged,
@ -692,7 +692,7 @@ class BlockAdapter(
clicked = onClickListener
)
}
is BlockViewHolder.Numbered -> {
is Numbered -> {
holder.bind(
item = blocks[position] as BlockView.Numbered,
onTextChanged = onTextChanged,
@ -701,7 +701,7 @@ class BlockAdapter(
clicked = onClickListener
)
}
is BlockViewHolder.Toggle -> {
is Toggle -> {
holder.bind(
item = blocks[position] as BlockView.Toggle,
onTextChanged = onTextChanged,

View file

@ -1,30 +1,20 @@
package com.agileburo.anytype.core_ui.features.page
import android.content.Context
import android.graphics.drawable.Drawable
import android.net.Uri
import android.text.Editable
import android.view.Gravity
import android.view.View
import android.view.ViewGroup
import android.widget.FrameLayout
import android.widget.ImageView
import android.widget.LinearLayout
import android.widget.TextView
import androidx.core.view.isVisible
import androidx.core.view.updateLayoutParams
import androidx.core.view.updatePadding
import androidx.recyclerview.widget.RecyclerView
import com.agileburo.anytype.core_ui.BuildConfig
import com.agileburo.anytype.core_ui.R
import com.agileburo.anytype.core_ui.common.Markup
import com.agileburo.anytype.core_ui.common.ThemeColor
import com.agileburo.anytype.core_ui.common.isLinksPresent
import com.agileburo.anytype.core_ui.extensions.color
import com.agileburo.anytype.core_ui.extensions.tint
import com.agileburo.anytype.core_ui.features.page.BlockViewDiffUtil.Companion.NUMBER_CHANGED
import com.agileburo.anytype.core_ui.features.page.BlockViewDiffUtil.Companion.SELECTION_CHANGED
import com.agileburo.anytype.core_ui.features.page.BlockViewDiffUtil.Companion.TOGGLE_EMPTY_STATE_CHANGED
import com.agileburo.anytype.core_ui.features.page.BlockViewDiffUtil.Payload
import com.agileburo.anytype.core_ui.menu.ContextMenuType
import com.agileburo.anytype.core_ui.tools.DefaultSpannableFactory
@ -52,11 +42,9 @@ import kotlinx.android.synthetic.main.item_block_code_snippet.view.*
import kotlinx.android.synthetic.main.item_block_contact.view.*
import kotlinx.android.synthetic.main.item_block_file.view.*
import kotlinx.android.synthetic.main.item_block_highlight.view.*
import kotlinx.android.synthetic.main.item_block_numbered.view.*
import kotlinx.android.synthetic.main.item_block_page.view.*
import kotlinx.android.synthetic.main.item_block_picture.view.*
import kotlinx.android.synthetic.main.item_block_text.view.*
import kotlinx.android.synthetic.main.item_block_toggle.view.*
import kotlinx.android.synthetic.main.item_block_video.view.*
import timber.log.Timber
import android.text.format.Formatter as FileSizeFormatter
@ -234,536 +222,6 @@ open class BlockViewHolder(view: View) : RecyclerView.ViewHolder(view) {
}
}
class Checkbox(
view: View,
onMarkupActionClicked: (Markup.Type, IntRange) -> Unit
) : BlockViewHolder(view), TextHolder, IndentableHolder, SupportNesting {
var mode = BlockView.Mode.EDIT
val checkbox: ImageView = itemView.checkboxIcon
private val container = itemView.checkboxBlockContentContainer
override val content: TextInputWidget = itemView.checkboxContent
override val root: View = itemView
init {
setup(onMarkupActionClicked, ContextMenuType.TEXT)
}
fun bind(
item: BlockView.Checkbox,
onTextChanged: (String, Editable) -> Unit,
onCheckboxClicked: (String) -> Unit,
onSelectionChanged: (String, IntRange) -> Unit,
onFocusChanged: (String, Boolean) -> Unit,
clicked: (ListenerType) -> Unit
) {
indentize(item)
if (item.mode == BlockView.Mode.READ) {
enableReadOnlyMode()
select(item)
updateTextColor(
context = itemView.context,
view = content,
isSelected = checkbox.isActivated
)
checkbox.isActivated = item.isChecked
setBlockText(text = item.text, markup = item, clicked = clicked)
} else {
enableEditMode()
select(item)
content.setOnLongClickListener(
EditorLongClickListener(
t = item.id,
click = { onBlockLongClick(root, it, clicked) }
)
)
content.clearTextWatchers()
checkbox.isActivated = item.isChecked
updateTextColor(
context = itemView.context,
view = content,
isSelected = checkbox.isActivated
)
if (item.marks.isLinksPresent()) {
content.setLinksClickable()
}
setBlockText(text = item.text, markup = item, clicked = clicked)
if (item.isFocused) setCursor(item)
setFocus(item)
checkbox.setOnClickListener {
if (mode == BlockView.Mode.EDIT) {
checkbox.isActivated = !checkbox.isActivated
updateTextColor(
context = itemView.context,
view = content,
isSelected = checkbox.isActivated
)
onCheckboxClicked(item.id)
}
}
content.setOnFocusChangeListener { _, hasFocus ->
onFocusChanged(item.id, hasFocus)
}
content.addTextChangedListener(
DefaultTextWatcher { text ->
onTextChanged(item.id, text)
}
)
content.selectionWatcher = {
onSelectionChanged(item.id, it)
}
}
}
override fun getMentionImageSizeAndPadding(): Pair<Int, Int> = with(itemView) {
Pair(
first = resources.getDimensionPixelSize(R.dimen.mention_span_image_size_default),
second = resources.getDimensionPixelSize(R.dimen.mention_span_image_padding_default)
)
}
override fun indentize(item: BlockView.Indentable) {
checkbox.updatePadding(left = item.indent * dimen(R.dimen.indent))
}
override fun enableEditMode() {
super.enableEditMode()
mode = BlockView.Mode.EDIT
}
override fun enableReadOnlyMode() {
super.enableReadOnlyMode()
mode = BlockView.Mode.READ
}
override fun select(item: BlockView.Selectable) {
container.isSelected = item.isSelected
}
private fun updateTextColor(context: Context, view: TextView, isSelected: Boolean) =
view.setTextColor(
context.color(
if (isSelected) R.color.checkbox_state_checked else R.color.black
)
)
}
class Bulleted(
view: View,
onMarkupActionClicked: (Markup.Type, IntRange) -> Unit
) : BlockViewHolder(view), TextHolder, IndentableHolder, SupportNesting {
val indent = itemView.bulletIndent
private val bullet = itemView.bullet
private val container = itemView.bulletBlockContainer
override val content: TextInputWidget = itemView.bulletedListContent
override val root: View = itemView
init {
setup(onMarkupActionClicked, ContextMenuType.TEXT)
}
fun bind(
item: BlockView.Bulleted,
onTextChanged: (String, Editable) -> Unit,
onSelectionChanged: (String, IntRange) -> Unit,
onFocusChanged: (String, Boolean) -> Unit,
clicked: (ListenerType) -> Unit
) {
indentize(item)
if (item.mode == BlockView.Mode.READ) {
enableReadOnlyMode()
select(item)
setBlockText(text = item.text, markup = item, clicked = clicked)
if (item.color != null)
setTextColor(item.color)
else
setTextColor(content.context.color(R.color.black))
} else {
enableEditMode()
select(item)
content.setOnLongClickListener(
EditorLongClickListener(
t = item.id,
click = { onBlockLongClick(root, it, clicked) }
)
)
content.clearTextWatchers()
if (item.marks.isLinksPresent()) {
content.setLinksClickable()
}
setBlockText(text = item.text, markup = item, clicked = clicked)
if (item.color != null) {
setTextColor(item.color)
} else {
setTextColor(content.context.color(R.color.black))
}
if (item.isFocused) setCursor(item)
setFocus(item)
content.addTextChangedListener(
DefaultTextWatcher { text ->
onTextChanged(item.id, text)
}
)
content.setOnFocusChangeListener { _, hasFocus ->
onFocusChanged(item.id, hasFocus)
}
content.selectionWatcher = {
onSelectionChanged(item.id, it)
}
}
}
override fun getMentionImageSizeAndPadding(): Pair<Int, Int> = with(itemView) {
Pair(
first = resources.getDimensionPixelSize(R.dimen.mention_span_image_size_default),
second = resources.getDimensionPixelSize(R.dimen.mention_span_image_padding_default)
)
}
override fun setTextColor(color: String) {
super.setTextColor(color)
bullet.setColorFilter(
ThemeColor.values().first { value ->
value.title == color
}.text
)
}
override fun setTextColor(color: Int) {
super.setTextColor(color)
bullet.tint(content.context.color(R.color.black))
}
override fun indentize(item: BlockView.Indentable) {
indent.updateLayoutParams { width = item.indent * dimen(R.dimen.indent) }
}
override fun select(item: BlockView.Selectable) {
container.isSelected = item.isSelected
}
}
class Numbered(
view: View,
onMarkupActionClicked: (Markup.Type, IntRange) -> Unit
) : BlockViewHolder(view), TextHolder, IndentableHolder, SupportNesting {
private val container = itemView.numberedBlockContentContainer
val number = itemView.number
override val content: TextInputWidget = itemView.numberedListContent
override val root: View = itemView
init {
setup(onMarkupActionClicked, ContextMenuType.TEXT)
}
fun bind(
item: BlockView.Numbered,
onTextChanged: (String, Editable) -> Unit,
onSelectionChanged: (String, IntRange) -> Unit,
onFocusChanged: (String, Boolean) -> Unit,
clicked: (ListenerType) -> Unit
) {
indentize(item)
if (item.mode == BlockView.Mode.READ) {
enableReadOnlyMode()
select(item)
number.gravity = when (item.number) {
in 1..19 -> Gravity.CENTER_HORIZONTAL
else -> Gravity.START
}
number.text = item.number.addDot()
setBlockText(text = item.text, markup = item, clicked = clicked)
if (item.color != null)
setTextColor(item.color)
else
setTextColor(content.context.color(R.color.black))
} else {
enableEditMode()
select(item)
content.setOnLongClickListener(
EditorLongClickListener(
t = item.id,
click = { onBlockLongClick(root, it, clicked) }
)
)
content.clearTextWatchers()
indentize(item)
number.gravity = when (item.number) {
in 1..19 -> Gravity.CENTER_HORIZONTAL
else -> Gravity.START
}
number.text = item.number.addDot()
if (item.marks.isLinksPresent()) {
content.setLinksClickable()
}
setBlockText(text = item.text, markup = item, clicked = clicked)
if (item.color != null)
setTextColor(item.color)
else
setTextColor(content.context.color(R.color.black))
if (item.isFocused) setCursor(item)
setFocus(item)
content.addTextChangedListener(
DefaultTextWatcher { text ->
onTextChanged(item.id, text)
}
)
content.setOnFocusChangeListener { _, hasFocus ->
onFocusChanged(item.id, hasFocus)
}
content.selectionWatcher = {
onSelectionChanged(item.id, it)
}
}
}
override fun getMentionImageSizeAndPadding(): Pair<Int, Int> = with(itemView) {
Pair(
first = resources.getDimensionPixelSize(R.dimen.mention_span_image_size_default),
second = resources.getDimensionPixelSize(R.dimen.mention_span_image_padding_default)
)
}
override fun processChangePayload(
payloads: List<Payload>,
item: BlockView,
onTextChanged: (String, Editable) -> Unit,
onSelectionChanged: (String, IntRange) -> Unit,
clicked: (ListenerType) -> Unit
) {
super.processChangePayload(payloads, item, onTextChanged, onSelectionChanged, clicked)
payloads.forEach { payload ->
if (payload.changes.contains(NUMBER_CHANGED))
number.text = "${(item as BlockView.Numbered).number}"
}
}
override fun indentize(item: BlockView.Indentable) {
number.updateLayoutParams<LinearLayout.LayoutParams> {
setMargins(
item.indent * dimen(R.dimen.indent),
0,
0,
0
)
}
}
override fun select(item: BlockView.Selectable) {
container.isSelected = item.isSelected
}
}
class Toggle(
view: View,
onMarkupActionClicked: (Markup.Type, IntRange) -> Unit
) : BlockViewHolder(view), TextHolder, IndentableHolder, SupportNesting {
private var mode = BlockView.Mode.EDIT
val toggle = itemView.toggle
private val line = itemView.guideline
private val placeholder = itemView.togglePlaceholder
private val container = itemView.toolbarBlockContentContainer
override val content: TextInputWidget = itemView.toggleContent
override val root: View = itemView
init {
setup(onMarkupActionClicked, ContextMenuType.TEXT)
}
fun bind(
item: BlockView.Toggle,
onTextChanged: (String, Editable) -> Unit,
onSelectionChanged: (String, IntRange) -> Unit,
onFocusChanged: (String, Boolean) -> Unit,
onToggleClicked: (String) -> Unit,
onTogglePlaceholderClicked: (String) -> Unit,
clicked: (ListenerType) -> Unit
) {
indentize(item)
if (item.mode == BlockView.Mode.READ) {
enableReadOnlyMode()
select(item)
setBlockText(text = item.text, markup = item, clicked = clicked)
if (item.color != null)
setTextColor(item.color)
else
setTextColor(content.context.color(R.color.black))
placeholder.isVisible = false
toggle.apply {
rotation = if (item.toggled) EXPANDED_ROTATION else COLLAPSED_ROTATION
}
} else {
enableEditMode()
select(item)
content.setOnLongClickListener(
EditorLongClickListener(
t = item.id,
click = { onBlockLongClick(root, it, clicked) }
)
)
if (item.marks.isLinksPresent()) {
content.setLinksClickable()
}
content.clearTextWatchers()
setBlockText(text = item.text, markup = item, clicked = clicked)
if (item.color != null) {
setTextColor(item.color)
} else {
setTextColor(content.context.color(R.color.black))
}
if (item.isFocused) setCursor(item)
setFocus(item)
setupTextWatcher(onTextChanged, item)
content.setOnFocusChangeListener { _, focused ->
item.isFocused = focused
onFocusChanged(item.id, focused)
}
content.selectionWatcher = {
onSelectionChanged(item.id, it)
}
placeholder.apply {
isVisible = item.isEmpty && item.toggled
setOnClickListener { onTogglePlaceholderClicked(item.id) }
}
}
toggle.apply {
rotation = if (item.toggled) EXPANDED_ROTATION else COLLAPSED_ROTATION
setOnClickListener {
if (mode == BlockView.Mode.EDIT) onToggleClicked(item.id)
}
}
}
override fun getMentionImageSizeAndPadding(): Pair<Int, Int> = with(itemView) {
Pair(
first = resources.getDimensionPixelSize(R.dimen.mention_span_image_size_default),
second = resources.getDimensionPixelSize(R.dimen.mention_span_image_padding_default)
)
}
override fun indentize(item: BlockView.Indentable) {
line.setGuidelineBegin(item.indent * dimen(R.dimen.indent))
}
override fun select(item: BlockView.Selectable) {
container.isSelected = item.isSelected
}
override fun enableReadOnlyMode() {
super.enableReadOnlyMode()
mode = BlockView.Mode.READ
}
override fun enableEditMode() {
super.enableEditMode()
mode = BlockView.Mode.EDIT
}
override fun processChangePayload(
payloads: List<Payload>,
item: BlockView,
onTextChanged: (String, Editable) -> Unit,
onSelectionChanged: (String, IntRange) -> Unit,
clicked: (ListenerType) -> Unit
) {
check(item is BlockView.Toggle) { "Expected a toggle block, but was: $item" }
super.processChangePayload(payloads, item, onTextChanged, onSelectionChanged, clicked)
payloads.forEach { payload ->
if (payload.changes.contains(TOGGLE_EMPTY_STATE_CHANGED))
placeholder.isVisible = item.isEmpty
}
}
companion object {
/**
* Rotation value for a toggle icon for expanded state.
*/
const val EXPANDED_ROTATION = 90f
/**
* Rotation value for a toggle icon for collapsed state.
*/
const val COLLAPSED_ROTATION = 0f
}
}
class Contact(view: View) : BlockViewHolder(view) {
private val name = itemView.name

View file

@ -1012,7 +1012,7 @@ class BlockAdapterTest {
adapter.bindViewHolder(holder, 0)
check(holder is BlockViewHolder.Checkbox)
check(holder is Checkbox)
val actual = holder.itemView.checkboxIcon.paddingLeft
@ -1047,7 +1047,7 @@ class BlockAdapterTest {
adapter.bindViewHolder(holder, 0)
check(holder is BlockViewHolder.Toggle)
check(holder is Toggle)
val actual =
(holder.itemView.guideline.layoutParams as ConstraintLayout.LayoutParams).guideBegin
@ -2689,7 +2689,7 @@ class BlockAdapterTest {
adapter.onBindViewHolder(holder, 0)
check(holder is BlockViewHolder.Bulleted)
check(holder is Bulleted)
assertEquals(
expected = InputType.TYPE_NULL,
@ -2730,7 +2730,7 @@ class BlockAdapterTest {
adapter.onBindViewHolder(holder, 0)
check(holder is BlockViewHolder.Bulleted)
check(holder is Bulleted)
assertEquals(
expected = InputType.TYPE_CLASS_TEXT or InputType.TYPE_TEXT_FLAG_NO_SUGGESTIONS,
@ -2771,7 +2771,7 @@ class BlockAdapterTest {
adapter.onBindViewHolder(holder, 0)
check(holder is BlockViewHolder.Bulleted)
check(holder is Bulleted)
// Testing
@ -2836,7 +2836,7 @@ class BlockAdapterTest {
adapter.onBindViewHolder(holder, 0)
check(holder is BlockViewHolder.Checkbox)
check(holder is Checkbox)
assertEquals(
expected = InputType.TYPE_NULL,
@ -2877,7 +2877,7 @@ class BlockAdapterTest {
adapter.onBindViewHolder(holder, 0)
check(holder is BlockViewHolder.Checkbox)
check(holder is Checkbox)
assertEquals(
expected = InputType.TYPE_CLASS_TEXT or InputType.TYPE_TEXT_FLAG_NO_SUGGESTIONS,
@ -2918,7 +2918,7 @@ class BlockAdapterTest {
adapter.onBindViewHolder(holder, 0)
check(holder is BlockViewHolder.Checkbox)
check(holder is Checkbox)
// Testing
@ -2984,7 +2984,7 @@ class BlockAdapterTest {
adapter.onBindViewHolder(holder, 0)
check(holder is BlockViewHolder.Numbered)
check(holder is Numbered)
assertEquals(
expected = InputType.TYPE_NULL,
@ -3026,7 +3026,7 @@ class BlockAdapterTest {
adapter.onBindViewHolder(holder, 0)
check(holder is BlockViewHolder.Numbered)
check(holder is Numbered)
assertEquals(
expected = InputType.TYPE_CLASS_TEXT or InputType.TYPE_TEXT_FLAG_NO_SUGGESTIONS,
@ -3068,7 +3068,7 @@ class BlockAdapterTest {
adapter.onBindViewHolder(holder, 0)
check(holder is BlockViewHolder.Numbered)
check(holder is Numbered)
// Testing
@ -3135,7 +3135,7 @@ class BlockAdapterTest {
adapter.onBindViewHolder(holder, 0)
check(holder is BlockViewHolder.Toggle)
check(holder is Toggle)
assertEquals(
expected = InputType.TYPE_NULL,
@ -3180,7 +3180,7 @@ class BlockAdapterTest {
adapter.onBindViewHolder(holder, 0)
check(holder is BlockViewHolder.Toggle)
check(holder is Toggle)
assertEquals(
expected = InputType.TYPE_CLASS_TEXT or InputType.TYPE_TEXT_FLAG_NO_SUGGESTIONS,
@ -3223,7 +3223,7 @@ class BlockAdapterTest {
adapter.onBindViewHolder(holder, 0)
check(holder is BlockViewHolder.Toggle)
check(holder is Toggle)
// Testing

View file

@ -7,9 +7,7 @@ import androidx.recyclerview.widget.LinearLayoutManager
import androidx.recyclerview.widget.RecyclerView
import androidx.test.core.app.ApplicationProvider
import com.agileburo.anytype.core_ui.MockDataFactory
import com.agileburo.anytype.core_ui.features.editor.holders.HeaderOne
import com.agileburo.anytype.core_ui.features.editor.holders.HeaderThree
import com.agileburo.anytype.core_ui.features.editor.holders.HeaderTwo
import com.agileburo.anytype.core_ui.features.editor.holders.*
import com.agileburo.anytype.core_ui.features.page.BlockAdapter
import com.agileburo.anytype.core_ui.features.page.BlockView
import com.agileburo.anytype.core_ui.features.page.BlockViewHolder
@ -234,7 +232,7 @@ class BlockAdapterCursorBindingTest {
adapter.onBindViewHolder(holder, 0)
check(holder is BlockViewHolder.Checkbox)
check(holder is Checkbox)
// Testing
@ -270,7 +268,7 @@ class BlockAdapterCursorBindingTest {
adapter.onBindViewHolder(holder, 0)
check(holder is BlockViewHolder.Bulleted)
check(holder is Bulleted)
// Testing
@ -307,7 +305,7 @@ class BlockAdapterCursorBindingTest {
adapter.onBindViewHolder(holder, 0)
check(holder is BlockViewHolder.Numbered)
check(holder is Numbered)
// Testing
@ -343,7 +341,7 @@ class BlockAdapterCursorBindingTest {
adapter.onBindViewHolder(holder, 0)
check(holder is BlockViewHolder.Toggle)
check(holder is Toggle)
// Testing

View file

@ -6,9 +6,7 @@ import androidx.recyclerview.widget.LinearLayoutManager
import androidx.recyclerview.widget.RecyclerView
import com.agileburo.anytype.core_ui.MockDataFactory
import com.agileburo.anytype.core_ui.R
import com.agileburo.anytype.core_ui.features.editor.holders.HeaderOne
import com.agileburo.anytype.core_ui.features.editor.holders.HeaderThree
import com.agileburo.anytype.core_ui.features.editor.holders.HeaderTwo
import com.agileburo.anytype.core_ui.features.editor.holders.*
import com.agileburo.anytype.core_ui.features.page.BlockView
import com.agileburo.anytype.core_ui.features.page.BlockViewDiffUtil
import com.agileburo.anytype.core_ui.features.page.BlockViewHolder
@ -262,7 +260,7 @@ class BlockAdapterIndentationTest : BlockAdapterTestSetup() {
adapter.onBindViewHolder(holder, 0)
check(holder is BlockViewHolder.Checkbox)
check(holder is Checkbox)
// Testing
@ -315,7 +313,7 @@ class BlockAdapterIndentationTest : BlockAdapterTestSetup() {
adapter.onBindViewHolder(holder, 0)
check(holder is BlockViewHolder.Numbered)
check(holder is Numbered)
// Testing

View file

@ -4,6 +4,7 @@ import android.os.Build
import androidx.recyclerview.widget.LinearLayoutManager
import androidx.recyclerview.widget.RecyclerView
import com.agileburo.anytype.core_ui.MockDataFactory
import com.agileburo.anytype.core_ui.features.editor.holders.Toggle
import com.agileburo.anytype.core_ui.features.page.BlockView
import com.agileburo.anytype.core_ui.features.page.BlockViewDiffUtil
import com.agileburo.anytype.core_ui.features.page.BlockViewHolder
@ -50,7 +51,7 @@ class BlockAdapterToggleTest : BlockAdapterTestSetup() {
// TESTING
check(holder is BlockViewHolder.Toggle)
check(holder is Toggle)
// Performing click in read-mode