mirror of
https://github.com/anyproto/anytype-kotlin.git
synced 2025-06-08 05:47:05 +09:00
DROID-478 Editor | Redesign | Link-to-object appearance as text (#2630)
* DROID-478 object link as text, xml updated * DROID-478 link to object as text, holder + xml * DROID-478 diff util, object type changed * DROID-478 object type changed * DROID-478 update preview model * DROID-478 create object icon, editor method * DROID-478 object preview, mapping update * DROID-478 object preview menu, show description for text preview * DROID-478 update task checked icon * DROID-478 holder fixes * DROID-478 fix paddings * DROID-478 task icon fix * DROID-478 link to object, archived + deleted states * DROID-478 amend click on archived/deleted links * DROID-478 link to object, loading state * DROID-478 object loading state, payload * DROID-478 fix indentize * DROID-478 design fixes * DROID-478 use icon none/small for text preview * DROID-478 fix tests * DROID-478 fixes * DROID-478 padding fix * DROID-478 enable link appearance * DROID-478 ci start * DROID-478 ci off * DROID-478 pr fix Co-authored-by: konstantiniiv <ki@anytype.io>
This commit is contained in:
parent
b03efcc788
commit
82fddb7b49
29 changed files with 449 additions and 250 deletions
|
@ -573,11 +573,7 @@ class BlockAdapter(
|
|||
}
|
||||
HOLDER_OBJECT_LINK_LOADING -> {
|
||||
LinkToObjectLoading(
|
||||
binding = ItemBlockObjectLinkLoadingBinding.inflate(
|
||||
LayoutInflater.from(parent.context),
|
||||
parent,
|
||||
false
|
||||
)
|
||||
ItemBlockObjectLinkLoadingBinding.inflate(inflater, parent, false)
|
||||
)
|
||||
}
|
||||
HOLDER_BOOKMARK -> {
|
||||
|
@ -1027,6 +1023,12 @@ class BlockAdapter(
|
|||
item = blocks[position]
|
||||
)
|
||||
}
|
||||
is LinkToObjectLoading -> {
|
||||
holder.processChangePayload(
|
||||
payloads = payloads.typeOf(),
|
||||
item = blocks[position]
|
||||
)
|
||||
}
|
||||
is Bookmark -> {
|
||||
holder.processChangePayload(
|
||||
payloads = payloads.typeOf(),
|
||||
|
@ -1274,6 +1276,12 @@ class BlockAdapter(
|
|||
clicked = onClickListener
|
||||
)
|
||||
}
|
||||
is LinkToObjectLoading -> {
|
||||
holder.bind(
|
||||
item = blocks[position] as BlockView.LinkToObject.Loading,
|
||||
clicked = onClickListener
|
||||
)
|
||||
}
|
||||
is Bookmark -> {
|
||||
holder.bind(
|
||||
item = blocks[position] as BlockView.Media.Bookmark,
|
||||
|
|
|
@ -153,6 +153,8 @@ class BlockViewDiffUtil(
|
|||
changes.add(OBJECT_DESCRIPTION_CHANGED)
|
||||
if (newBlock.background != oldBlock.background)
|
||||
changes.add(BACKGROUND_COLOR_CHANGED)
|
||||
if (newBlock.objectTypeName != oldBlock.objectTypeName)
|
||||
changes.add(OBJECT_TYPE_CHANGED)
|
||||
}
|
||||
|
||||
if (newBlock is BlockView.LinkToObject.Default.Card && oldBlock is BlockView.LinkToObject.Default.Card) {
|
||||
|
@ -271,6 +273,7 @@ class BlockViewDiffUtil(
|
|||
val isObjectIconChanged: Boolean get() = changes.contains(OBJECT_ICON_CHANGED)
|
||||
val isObjectDescriptionChanged: Boolean get() = changes.contains(OBJECT_DESCRIPTION_CHANGED)
|
||||
val isObjectCoverChanged: Boolean get() = changes.contains(OBJECT_COVER_CHANGED)
|
||||
val isObjectTypeChanged: Boolean get() = changes.contains(OBJECT_TYPE_CHANGED)
|
||||
|
||||
val isLatexChanged: Boolean get() = changes.contains(LATEX_CHANGED)
|
||||
|
||||
|
@ -317,10 +320,11 @@ class BlockViewDiffUtil(
|
|||
const val RELATION_NAME_CHANGED = 22
|
||||
const val RELATION_VALUE_CHANGED = 23
|
||||
|
||||
const val OBJECT_TITLE_CHANGED = 19
|
||||
const val OBJECT_ICON_CHANGED = 20
|
||||
const val OBJECT_COVER_CHANGED = 24
|
||||
const val OBJECT_DESCRIPTION_CHANGED = 25
|
||||
const val OBJECT_TITLE_CHANGED = 319
|
||||
const val OBJECT_ICON_CHANGED = 320
|
||||
const val OBJECT_COVER_CHANGED = 321
|
||||
const val OBJECT_DESCRIPTION_CHANGED = 322
|
||||
const val OBJECT_TYPE_CHANGED = 323
|
||||
|
||||
const val DECORATION_CHANGED = 27
|
||||
const val CALLOUT_ICON_CHANGED = 28
|
||||
|
|
|
@ -2,11 +2,10 @@ package com.anytypeio.anytype.core_ui.features.editor.holders.other
|
|||
|
||||
import android.text.Spannable
|
||||
import android.text.SpannableString
|
||||
import android.text.style.UnderlineSpan
|
||||
import android.text.style.LeadingMarginSpan
|
||||
import android.widget.FrameLayout
|
||||
import android.widget.TextView
|
||||
import androidx.core.view.updateLayoutParams
|
||||
import androidx.core.view.updatePadding
|
||||
import androidx.recyclerview.widget.RecyclerView
|
||||
import com.anytypeio.anytype.core_ui.BuildConfig
|
||||
import com.anytypeio.anytype.core_ui.R
|
||||
|
@ -18,7 +17,6 @@ import com.anytypeio.anytype.core_ui.features.editor.BlockViewDiffUtil
|
|||
import com.anytypeio.anytype.core_ui.features.editor.BlockViewHolder
|
||||
import com.anytypeio.anytype.core_ui.features.editor.EditorTouchProcessor
|
||||
import com.anytypeio.anytype.core_ui.features.editor.SupportCustomTouchProcessor
|
||||
import com.anytypeio.anytype.core_ui.features.editor.SupportNesting
|
||||
import com.anytypeio.anytype.core_ui.features.editor.decoration.DecoratableViewHolder
|
||||
import com.anytypeio.anytype.core_utils.ext.dimen
|
||||
import com.anytypeio.anytype.core_utils.ext.gone
|
||||
|
@ -36,8 +34,7 @@ class LinkToObject(
|
|||
BlockViewHolder.IndentableHolder,
|
||||
BlockViewHolder.DragAndDropHolder,
|
||||
DecoratableViewHolder,
|
||||
SupportCustomTouchProcessor,
|
||||
SupportNesting {
|
||||
SupportCustomTouchProcessor {
|
||||
|
||||
private val root = binding.root
|
||||
private val container = binding.container
|
||||
|
@ -45,6 +42,8 @@ class LinkToObject(
|
|||
private val objectIcon = binding.objectIconWidget
|
||||
private val objectIconContainer = binding.iconObjectContainer
|
||||
private val title = binding.text
|
||||
private val description = binding.tvDescription
|
||||
private val objectType = binding.tvObjectType
|
||||
|
||||
override val editorTouchProcessor = EditorTouchProcessor(
|
||||
fallback = { e -> itemView.onTouchEvent(e) }
|
||||
|
@ -54,20 +53,7 @@ class LinkToObject(
|
|||
|
||||
init {
|
||||
itemView.setOnTouchListener { v, e -> editorTouchProcessor.process(v, e) }
|
||||
if (!BuildConfig.NESTED_DECORATION_ENABLED) {
|
||||
root.updatePadding(
|
||||
left = dimen(R.dimen.default_document_item_padding_start),
|
||||
right = dimen(R.dimen.default_document_item_padding_end)
|
||||
)
|
||||
root.updateLayoutParams<RecyclerView.LayoutParams> {
|
||||
bottomMargin = dimen(R.dimen.default_graphic_text_root_margin_bottom)
|
||||
topMargin = dimen(R.dimen.default_graphic_text_root_margin_top)
|
||||
}
|
||||
container.updatePadding(
|
||||
left = dimen(R.dimen.default_graphic_text_container_padding_start),
|
||||
right = dimen(R.dimen.default_graphic_text_container_padding_end)
|
||||
)
|
||||
}
|
||||
applyDefaultOffsets()
|
||||
}
|
||||
|
||||
fun bind(
|
||||
|
@ -76,10 +62,14 @@ class LinkToObject(
|
|||
) {
|
||||
indentize(item)
|
||||
|
||||
container.isSelected = item.isSelected
|
||||
applySelectedState(item)
|
||||
|
||||
applyText(item)
|
||||
|
||||
applyDescription(item)
|
||||
|
||||
applyObjectType(item)
|
||||
|
||||
applySearchHighlight(item)
|
||||
|
||||
applyImageOrEmoji(item)
|
||||
|
@ -89,6 +79,10 @@ class LinkToObject(
|
|||
itemView.setOnClickListener { clicked(ListenerType.LinkToObject(item.id)) }
|
||||
}
|
||||
|
||||
private fun applySelectedState(item: BlockView.LinkToObject.Default.Text) {
|
||||
container.isSelected = item.isSelected
|
||||
}
|
||||
|
||||
private fun applyText(item: BlockView.LinkToObject.Default.Text) {
|
||||
val name = item.text
|
||||
when {
|
||||
|
@ -98,27 +92,59 @@ class LinkToObject(
|
|||
}
|
||||
name.isEmpty() -> {
|
||||
val sb = SpannableString(untitled)
|
||||
sb.setSpan(UnderlineSpan(), 0, sb.length, 0)
|
||||
if (item.icon !is ObjectIcon.None) {
|
||||
val firstLineMargin =
|
||||
itemView.resources.getDimensionPixelOffset(R.dimen.default_graphic_text_text_first_line_margin_start)
|
||||
sb.setSpan(
|
||||
LeadingMarginSpan.Standard(firstLineMargin, 0), 0, sb.length, 0
|
||||
)
|
||||
}
|
||||
title.visible()
|
||||
title.setText(sb, TextView.BufferType.EDITABLE)
|
||||
title.text = sb
|
||||
}
|
||||
else -> {
|
||||
val sb = SpannableString(name)
|
||||
sb.setSpan(UnderlineSpan(), 0, sb.length, 0)
|
||||
if (item.icon !is ObjectIcon.None) {
|
||||
val firstLineMargin =
|
||||
itemView.resources.getDimensionPixelOffset(R.dimen.default_graphic_text_text_first_line_margin_start)
|
||||
sb.setSpan(
|
||||
LeadingMarginSpan.Standard(firstLineMargin, 0), 0, sb.length, 0
|
||||
)
|
||||
}
|
||||
title.visible()
|
||||
title.setText(sb, TextView.BufferType.EDITABLE)
|
||||
title.text = sb
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private fun applyDescription(item: BlockView.LinkToObject.Default.Text) {
|
||||
if (item.description.isNullOrBlank()) {
|
||||
description.gone()
|
||||
} else {
|
||||
description.visible()
|
||||
description.text = item.description
|
||||
}
|
||||
}
|
||||
|
||||
private fun applyObjectType(item: BlockView.LinkToObject.Default.Text) {
|
||||
if (item.objectTypeName.isNullOrBlank()) {
|
||||
objectType.gone()
|
||||
} else {
|
||||
objectType.visible()
|
||||
objectType.text = item.objectTypeName
|
||||
}
|
||||
}
|
||||
|
||||
private fun applyImageOrEmoji(item: BlockView.LinkToObject.Default.Text) {
|
||||
when (item.icon) {
|
||||
ObjectIcon.None -> {
|
||||
objectIconContainer.gone()
|
||||
applyText(item)
|
||||
}
|
||||
else -> {
|
||||
objectIconContainer.visible()
|
||||
objectIcon.setIcon(item.icon)
|
||||
applyText(item)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -166,18 +192,27 @@ class LinkToObject(
|
|||
fun processChangePayload(payloads: List<BlockViewDiffUtil.Payload>, item: BlockView) {
|
||||
check(item is BlockView.LinkToObject.Default.Text) { "Expected a link to object block, but was: $item" }
|
||||
payloads.forEach { payload ->
|
||||
if (payload.changes.contains(BlockViewDiffUtil.SELECTION_CHANGED)) {
|
||||
container.isSelected = item.isSelected
|
||||
if (payload.isSelectionChanged) {
|
||||
applySelectedState(item)
|
||||
}
|
||||
if (payload.isSearchHighlightChanged) {
|
||||
applySearchHighlight(item)
|
||||
}
|
||||
if (payload.isObjectTitleChanged)
|
||||
if (payload.isObjectTitleChanged) {
|
||||
applyText(item)
|
||||
if (payload.isObjectIconChanged)
|
||||
}
|
||||
if (payload.isObjectIconChanged) {
|
||||
applyImageOrEmoji(item)
|
||||
if (payload.isBackgroundColorChanged)
|
||||
}
|
||||
if (payload.isBackgroundColorChanged) {
|
||||
applyBackground(item.background)
|
||||
}
|
||||
if (payload.isObjectDescriptionChanged) {
|
||||
applyDescription(item)
|
||||
}
|
||||
if (payload.isObjectTypeChanged) {
|
||||
applyObjectType(item)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -191,12 +226,26 @@ class LinkToObject(
|
|||
if (BuildConfig.NESTED_DECORATION_ENABLED) {
|
||||
decoratableContainer.decorate(decorations) { rect ->
|
||||
binding.container.updateLayoutParams<FrameLayout.LayoutParams> {
|
||||
marginStart = dimen(R.dimen.default_indent) + rect.left
|
||||
marginStart = dimen(R.dimen.dp_8) + rect.left
|
||||
marginEnd = dimen(R.dimen.dp_8) + rect.right
|
||||
bottomMargin = rect.bottom
|
||||
// TODO handle top and bottom offsets
|
||||
bottomMargin = if (rect.bottom > 0) {
|
||||
rect.bottom
|
||||
} else {
|
||||
dimen(R.dimen.dp_2)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private fun applyDefaultOffsets() {
|
||||
if (!BuildConfig.NESTED_DECORATION_ENABLED) {
|
||||
container.updateLayoutParams<FrameLayout.LayoutParams> {
|
||||
marginStart = dimen(R.dimen.default_document_item_padding_start)
|
||||
marginEnd = dimen(R.dimen.default_document_item_padding_end)
|
||||
topMargin = dimen(R.dimen.default_graphic_text_root_margin_top)
|
||||
bottomMargin = dimen(R.dimen.default_graphic_text_root_margin_bottom)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
|
@ -1,16 +1,15 @@
|
|||
package com.anytypeio.anytype.core_ui.features.editor.holders.other
|
||||
|
||||
import android.text.Spannable
|
||||
import android.text.SpannableStringBuilder
|
||||
import android.widget.FrameLayout
|
||||
import android.widget.TextView
|
||||
import androidx.core.view.updateLayoutParams
|
||||
import androidx.core.view.updatePadding
|
||||
import androidx.recyclerview.widget.RecyclerView
|
||||
import com.anytypeio.anytype.core_ui.BuildConfig
|
||||
import com.anytypeio.anytype.core_ui.R
|
||||
import com.anytypeio.anytype.core_ui.common.SearchHighlightSpan
|
||||
import com.anytypeio.anytype.core_ui.common.SearchTargetHighlightSpan
|
||||
import com.anytypeio.anytype.core_ui.common.Span
|
||||
import com.anytypeio.anytype.core_ui.databinding.ItemBlockObjectLinkArchiveBinding
|
||||
import com.anytypeio.anytype.core_ui.features.editor.BlockViewDiffUtil
|
||||
import com.anytypeio.anytype.core_ui.features.editor.BlockViewHolder
|
||||
|
@ -19,17 +18,11 @@ import com.anytypeio.anytype.core_ui.features.editor.SupportCustomTouchProcessor
|
|||
import com.anytypeio.anytype.core_ui.features.editor.SupportNesting
|
||||
import com.anytypeio.anytype.core_ui.features.editor.decoration.DecoratableViewHolder
|
||||
import com.anytypeio.anytype.core_ui.features.editor.decoration.EditorDecorationContainer
|
||||
import com.anytypeio.anytype.core_utils.ext.VALUE_ROUNDED
|
||||
import com.anytypeio.anytype.core_utils.ext.dimen
|
||||
import com.anytypeio.anytype.core_utils.ext.removeSpans
|
||||
import com.anytypeio.anytype.core_utils.ext.visible
|
||||
import com.anytypeio.anytype.emojifier.Emojifier
|
||||
import com.anytypeio.anytype.presentation.editor.editor.Markup
|
||||
import com.anytypeio.anytype.presentation.editor.editor.listener.ListenerType
|
||||
import com.anytypeio.anytype.presentation.editor.editor.model.BlockView
|
||||
import com.anytypeio.anytype.presentation.editor.editor.model.BlockView.Searchable.Field.Companion.DEFAULT_SEARCH_FIELD_KEY
|
||||
import com.bumptech.glide.Glide
|
||||
import com.bumptech.glide.load.engine.DiskCacheStrategy
|
||||
|
||||
class LinkToObjectArchive(
|
||||
val binding: ItemBlockObjectLinkArchiveBinding
|
||||
|
@ -40,13 +33,9 @@ class LinkToObjectArchive(
|
|||
SupportCustomTouchProcessor,
|
||||
SupportNesting {
|
||||
|
||||
private val root = binding.root
|
||||
private val untitled = itemView.resources.getString(R.string.untitled)
|
||||
private val archived = itemView.resources.getString(R.string.archived)
|
||||
private val icon = binding.pageIcon
|
||||
private val emoji = binding.linkEmoji
|
||||
private val image = binding.linkImage
|
||||
private val title = binding.pageTitle
|
||||
private val guideline = binding.pageGuideline
|
||||
|
||||
override val editorTouchProcessor = EditorTouchProcessor(
|
||||
fallback = { e -> itemView.onTouchEvent(e) }
|
||||
|
@ -69,69 +58,23 @@ class LinkToObjectArchive(
|
|||
itemView.isSelected = item.isSelected
|
||||
|
||||
val text = if (item.text.isNullOrEmpty()) {
|
||||
SpannableStringBuilder("$untitled $archived").apply {
|
||||
setSpan(
|
||||
Span.Keyboard(VALUE_ROUNDED),
|
||||
untitled.length + 1,
|
||||
untitled.length + 1 + archived.length,
|
||||
Markup.DEFAULT_SPANNABLE_FLAG
|
||||
)
|
||||
}
|
||||
untitled
|
||||
} else {
|
||||
SpannableStringBuilder("${item.text} $archived").apply {
|
||||
setSpan(
|
||||
Span.Keyboard(VALUE_ROUNDED),
|
||||
item.text!!.length + 1,
|
||||
item.text!!.length + 1 + archived.length,
|
||||
Markup.DEFAULT_SPANNABLE_FLAG
|
||||
)
|
||||
}
|
||||
item.text
|
||||
}
|
||||
|
||||
title.setText(text, TextView.BufferType.EDITABLE)
|
||||
|
||||
applySearchHighlight(item)
|
||||
|
||||
when {
|
||||
item.emoji != null -> {
|
||||
image.setImageDrawable(null)
|
||||
try {
|
||||
Glide
|
||||
.with(emoji)
|
||||
.load(Emojifier.uri(item.emoji!!))
|
||||
.diskCacheStrategy(DiskCacheStrategy.ALL)
|
||||
.into(emoji)
|
||||
} catch (e: Exception) {
|
||||
icon.setImageResource(R.drawable.ic_block_page_without_emoji)
|
||||
}
|
||||
}
|
||||
item.image != null -> {
|
||||
image.visible()
|
||||
Glide
|
||||
.with(image)
|
||||
.load(item.image)
|
||||
.centerInside()
|
||||
.circleCrop()
|
||||
.into(image)
|
||||
}
|
||||
item.isEmpty -> {
|
||||
icon.setImageResource(R.drawable.ic_block_empty_page)
|
||||
image.setImageDrawable(null)
|
||||
}
|
||||
else -> {
|
||||
icon.setImageResource(R.drawable.ic_block_page_without_emoji)
|
||||
image.setImageDrawable(null)
|
||||
}
|
||||
}
|
||||
|
||||
itemView.setOnClickListener { clicked(ListenerType.LinkToObjectArchived(item.id)) }
|
||||
}
|
||||
|
||||
override fun indentize(item: BlockView.Indentable) {
|
||||
if (!BuildConfig.NESTED_DECORATION_ENABLED) {
|
||||
guideline.setGuidelineBegin(
|
||||
item.indent * dimen(R.dimen.indent)
|
||||
)
|
||||
root.updateLayoutParams<RecyclerView.LayoutParams> {
|
||||
marginStart = item.indent * dimen(R.dimen.indent)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -183,11 +126,18 @@ class LinkToObjectArchive(
|
|||
if (BuildConfig.NESTED_DECORATION_ENABLED) {
|
||||
decoratableContainer.decorate(decorations) { rect ->
|
||||
binding.content.updateLayoutParams<FrameLayout.LayoutParams> {
|
||||
marginStart = dimen(R.dimen.default_indent) + rect.left
|
||||
marginStart = dimen(R.dimen.dp_8) + rect.left
|
||||
marginEnd = dimen(R.dimen.dp_8) + rect.right
|
||||
bottomMargin = rect.bottom
|
||||
// TODO handle top and bottom offsets
|
||||
bottomMargin = if (rect.bottom > 0) {
|
||||
rect.bottom
|
||||
} else {
|
||||
dimen(R.dimen.dp_2)
|
||||
}
|
||||
}
|
||||
binding.content.updatePadding(
|
||||
left = dimen(R.dimen.default_document_content_padding_start),
|
||||
right = dimen(R.dimen.default_document_item_padding_end)
|
||||
)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -85,7 +85,7 @@ class LinkToObjectCard(
|
|||
|
||||
applyImageOrEmoji(item)
|
||||
|
||||
applyType(item)
|
||||
applyObjectType(item)
|
||||
|
||||
itemView.setOnClickListener { clicked(ListenerType.LinkToObject(item.id)) }
|
||||
}
|
||||
|
@ -198,6 +198,8 @@ class LinkToObjectCard(
|
|||
applyCover(item)
|
||||
if (payload.isBackgroundColorChanged)
|
||||
applyBackground(item.background)
|
||||
if (payload.isObjectTypeChanged)
|
||||
applyObjectType(item)
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -274,8 +276,8 @@ class LinkToObjectCard(
|
|||
}
|
||||
}
|
||||
|
||||
private fun applyType(item: BlockView.LinkToObject.Default.Card) {
|
||||
if (item.objectTypeName != null) {
|
||||
private fun applyObjectType(item: BlockView.LinkToObject.Default.Card) {
|
||||
if (!item.objectTypeName.isNullOrBlank()) {
|
||||
type.text = item.objectTypeName
|
||||
type.visible()
|
||||
} else {
|
||||
|
|
|
@ -3,6 +3,7 @@ package com.anytypeio.anytype.core_ui.features.editor.holders.other
|
|||
import android.widget.FrameLayout
|
||||
import androidx.core.view.updateLayoutParams
|
||||
import androidx.core.view.updatePadding
|
||||
import androidx.recyclerview.widget.RecyclerView
|
||||
import com.anytypeio.anytype.core_ui.BuildConfig
|
||||
import com.anytypeio.anytype.core_ui.R
|
||||
import com.anytypeio.anytype.core_ui.databinding.ItemBlockObjectLinkDeleteBinding
|
||||
|
@ -24,6 +25,7 @@ class LinkToObjectDelete(
|
|||
DecoratableViewHolder,
|
||||
SupportCustomTouchProcessor {
|
||||
|
||||
private val root = binding.root
|
||||
private val guideline = binding.pageGuideline
|
||||
|
||||
override val decoratableContainer: EditorDecorationContainer
|
||||
|
@ -49,7 +51,9 @@ class LinkToObjectDelete(
|
|||
|
||||
override fun indentize(item: BlockView.Indentable) {
|
||||
if (!BuildConfig.NESTED_DECORATION_ENABLED) {
|
||||
guideline.setGuidelineBegin(item.indent * dimen(R.dimen.indent))
|
||||
root.updateLayoutParams<RecyclerView.LayoutParams> {
|
||||
marginStart = item.indent * dimen(R.dimen.indent)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -66,11 +70,18 @@ class LinkToObjectDelete(
|
|||
if (BuildConfig.NESTED_DECORATION_ENABLED) {
|
||||
decoratableContainer.decorate(decorations) { rect ->
|
||||
binding.content.updateLayoutParams<FrameLayout.LayoutParams> {
|
||||
marginStart = dimen(R.dimen.default_indent) + rect.left
|
||||
marginStart = dimen(R.dimen.dp_8) + rect.left
|
||||
marginEnd = dimen(R.dimen.dp_8) + rect.right
|
||||
bottomMargin = rect.bottom
|
||||
// TODO handle top and bottom offsets
|
||||
bottomMargin = if (rect.bottom > 0) {
|
||||
rect.bottom
|
||||
} else {
|
||||
dimen(R.dimen.dp_2)
|
||||
}
|
||||
}
|
||||
binding.content.updatePadding(
|
||||
left = dimen(R.dimen.default_document_content_padding_start),
|
||||
right = dimen(R.dimen.default_document_item_padding_end)
|
||||
)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,19 +1,51 @@
|
|||
package com.anytypeio.anytype.core_ui.features.editor.holders.other
|
||||
|
||||
import androidx.core.view.updatePadding
|
||||
import androidx.core.view.updateLayoutParams
|
||||
import androidx.recyclerview.widget.RecyclerView
|
||||
import com.anytypeio.anytype.core_ui.BuildConfig
|
||||
import com.anytypeio.anytype.core_ui.R
|
||||
import com.anytypeio.anytype.core_ui.databinding.ItemBlockObjectLinkLoadingBinding
|
||||
import com.anytypeio.anytype.core_ui.features.editor.BlockViewDiffUtil
|
||||
import com.anytypeio.anytype.core_ui.features.editor.BlockViewHolder
|
||||
import com.anytypeio.anytype.core_utils.ext.dimen
|
||||
import com.anytypeio.anytype.presentation.editor.editor.listener.ListenerType
|
||||
import com.anytypeio.anytype.presentation.editor.editor.model.BlockView
|
||||
|
||||
class LinkToObjectLoading(binding: ItemBlockObjectLinkLoadingBinding) :
|
||||
BlockViewHolder(binding.root),
|
||||
BlockViewHolder.IndentableHolder {
|
||||
|
||||
private val root = binding.root
|
||||
private val container = binding.container
|
||||
|
||||
fun bind(
|
||||
item: BlockView.LinkToObject.Loading,
|
||||
clicked: (ListenerType) -> Unit
|
||||
) {
|
||||
|
||||
applySelectedState(item)
|
||||
|
||||
itemView.setOnClickListener { clicked(ListenerType.LinkToObjectLoading(item.id)) }
|
||||
}
|
||||
|
||||
private fun applySelectedState(item: BlockView.LinkToObject.Loading) {
|
||||
container.isSelected = item.isSelected
|
||||
}
|
||||
|
||||
fun processChangePayload(payloads: List<BlockViewDiffUtil.Payload>, item: BlockView) {
|
||||
check(item is BlockView.LinkToObject.Loading) { "Expected a link to object block, but was: $item" }
|
||||
payloads.forEach { payload ->
|
||||
if (payload.isSelectionChanged) {
|
||||
applySelectedState(item)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
override fun indentize(item: BlockView.Indentable) {
|
||||
itemView.updatePadding(
|
||||
left = dimen(R.dimen.default_document_content_padding_start) + item.indent * dimen(R.dimen.indent)
|
||||
)
|
||||
if (!BuildConfig.NESTED_DECORATION_ENABLED) {
|
||||
root.updateLayoutParams<RecyclerView.LayoutParams> {
|
||||
marginStart = item.indent * dimen(R.dimen.indent)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
|
@ -257,7 +257,7 @@ class ObjectIconWidget @JvmOverloads constructor(
|
|||
fun setCheckbox(isChecked: Boolean?) {
|
||||
with(binding) {
|
||||
ivCheckbox.visible()
|
||||
ivCheckbox.isSelected = isChecked ?: false
|
||||
ivCheckbox.isEnabled = isChecked ?: false
|
||||
initialContainer.invisible()
|
||||
emojiContainer.invisible()
|
||||
ivBookmark.gone()
|
||||
|
|
|
@ -4,16 +4,7 @@
|
|||
android:viewportWidth="20"
|
||||
android:viewportHeight="20">
|
||||
<path
|
||||
android:pathData="M2.2222,9.4449L8.3333,16.6671L17.7777,2.2227"
|
||||
android:strokeWidth="2"
|
||||
android:fillColor="#00000000"
|
||||
android:strokeColor="#57C600"/>
|
||||
<path
|
||||
android:pathData="M0,5C0,2.2386 2.2386,0 5,0H15C17.7614,0 20,2.2386 20,5V15C20,17.7614 17.7614,20 15,20H5C2.2386,20 0,17.7614 0,15V5Z"
|
||||
android:fillColor="#57C600"/>
|
||||
<path
|
||||
android:pathData="M5.5,9.5034L9.5,14L15,5"
|
||||
android:strokeWidth="1.5"
|
||||
android:fillColor="#00000000"
|
||||
android:strokeColor="#ffffff"/>
|
||||
android:pathData="M17.033,4.564L8.853,16.561L3,10.708L4.414,9.294L8.561,13.44L15.381,3.438L17.033,4.564Z"
|
||||
android:fillColor="#5DD400"
|
||||
android:fillType="evenOdd"/>
|
||||
</vector>
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<selector xmlns:android="http://schemas.android.com/apk/res/android">
|
||||
<item android:drawable="@drawable/ic_data_view_grid_checkbox_checked" android:state_selected="true" />
|
||||
<item android:drawable="@drawable/ic_data_view_grid_checkbox" android:state_selected="false" />
|
||||
<item android:drawable="@drawable/ic_data_view_grid_checkbox_checked" android:state_enabled="true" />
|
||||
<item android:drawable="@drawable/ic_data_view_grid_checkbox" android:state_enabled="false" />
|
||||
</selector>
|
|
@ -16,48 +16,89 @@
|
|||
android:id="@+id/container"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:paddingStart="@dimen/default_document_content_padding_start"
|
||||
android:paddingEnd="@dimen/default_document_content_padding_start"
|
||||
android:background="@drawable/item_block_multi_select_mode_selector"
|
||||
tools:background="@drawable/item_block_multi_select_selected">
|
||||
|
||||
<androidx.constraintlayout.widget.Guideline
|
||||
android:id="@+id/guideline"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:orientation="vertical"
|
||||
app:layout_constraintGuide_begin="0dp" />
|
||||
|
||||
<FrameLayout
|
||||
android:id="@+id/iconObjectContainer"
|
||||
style="@style/DefaultGraphicTextBlockGraphicStyle"
|
||||
app:layout_constraintStart_toEndOf="@id/guideline"
|
||||
app:layout_constraintTop_toTopOf="parent">
|
||||
android:layout_width="24dp"
|
||||
android:layout_height="24dp"
|
||||
android:layout_marginTop="1dp"
|
||||
android:layout_marginBottom="3dp"
|
||||
app:layout_constraintStart_toStartOf="parent"
|
||||
app:layout_constraintTop_toTopOf="parent"
|
||||
app:layout_goneMarginStart="0dp"
|
||||
tools:visibility="visible">
|
||||
|
||||
<com.anytypeio.anytype.core_ui.widgets.ObjectIconWidget
|
||||
android:id="@+id/objectIconWidget"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_gravity="center"
|
||||
app:checkboxSize="@dimen/dp_20"
|
||||
app:checkboxSize="18dp"
|
||||
app:emojiSize="20dp"
|
||||
app:hasEmojiRounded8Background="false"
|
||||
app:hasInitialRounded8Background="true"
|
||||
app:imageCornerRadius="@dimen/list_item_object_image_corner_radius_small"
|
||||
app:imageSize="20dp"
|
||||
app:initialTextSize="13sp" />
|
||||
app:initialTextSize="13sp"
|
||||
tools:background="@drawable/ic_action_background" />
|
||||
|
||||
</FrameLayout>
|
||||
|
||||
<TextView
|
||||
android:id="@+id/text"
|
||||
style="@style/DefaultGraphicTextBlockTextStyle"
|
||||
style="@style/ObjectLinkBlockTextStyle"
|
||||
android:layout_width="0dp"
|
||||
android:layout_height="wrap_content"
|
||||
app:layout_constraintBottom_toBottomOf="parent"
|
||||
android:layout_marginTop="1dp"
|
||||
android:layout_marginBottom="1dp"
|
||||
android:ellipsize="end"
|
||||
android:maxLines="3"
|
||||
app:layout_constraintBottom_toTopOf="@+id/tvDescription"
|
||||
app:layout_constraintEnd_toEndOf="parent"
|
||||
app:layout_constraintStart_toEndOf="@+id/iconObjectContainer"
|
||||
app:layout_constraintStart_toStartOf="parent"
|
||||
app:layout_constraintTop_toTopOf="parent"
|
||||
app:layout_goneMarginStart="0dp"
|
||||
tools:text="Partnership terms" />
|
||||
tools:text="In the early days of the Civil War, rumors of gold in the
|
||||
frozen Klondike brought hordes of newcomers to the Pacific Northwest.
|
||||
Anxious to compete, Russian prospectors commissioned inventor Leviticus
|
||||
Blue to create a great machine that could mine through Alaska’s ice.
|
||||
Thus was Dr. Blue’s Incredible Bone-Shaking Drill Engine born." />
|
||||
|
||||
<TextView
|
||||
android:id="@+id/tvObjectType"
|
||||
style="@style/ObjectLinkBlockRelationsStyle"
|
||||
android:layout_width="0dp"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_marginTop="3dp"
|
||||
android:layout_marginBottom="1dp"
|
||||
android:ellipsize="end"
|
||||
android:maxLines="1"
|
||||
app:layout_constraintBottom_toBottomOf="parent"
|
||||
app:layout_constraintEnd_toEndOf="parent"
|
||||
app:layout_constraintStart_toStartOf="parent"
|
||||
app:layout_constraintTop_toBottomOf="@id/tvDescription"
|
||||
tools:text="Set"
|
||||
tools:visibility="visible" />
|
||||
|
||||
<TextView
|
||||
android:id="@+id/tvDescription"
|
||||
style="@style/ObjectLinkBlockRelationsStyle"
|
||||
android:layout_width="0dp"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_marginTop="3dp"
|
||||
android:layout_marginBottom="1dp"
|
||||
android:ellipsize="end"
|
||||
android:maxLines="1"
|
||||
app:layout_constraintBottom_toTopOf="@+id/tvObjectType"
|
||||
app:layout_constraintEnd_toEndOf="parent"
|
||||
app:layout_constraintStart_toStartOf="parent"
|
||||
app:layout_constraintTop_toBottomOf="@id/text"
|
||||
tools:text="@string/default_text_placeholder"
|
||||
tools:visibility="visible" />
|
||||
|
||||
</androidx.constraintlayout.widget.ConstraintLayout>
|
||||
</FrameLayout>
|
|
@ -24,43 +24,30 @@
|
|||
android:orientation="vertical"
|
||||
app:layout_constraintGuide_begin="0dp" />
|
||||
|
||||
<FrameLayout
|
||||
android:id="@+id/pageIconContainer"
|
||||
<ImageView
|
||||
android:id="@+id/ivIcon"
|
||||
android:layout_width="24dp"
|
||||
android:layout_height="24dp"
|
||||
app:layout_constraintBottom_toBottomOf="parent"
|
||||
app:layout_constraintStart_toEndOf="@id/pageGuideline"
|
||||
app:layout_constraintTop_toTopOf="parent">
|
||||
app:layout_constraintTop_toTopOf="parent"
|
||||
android:scaleType="centerInside"
|
||||
android:src="@drawable/ic_non_existent_object">
|
||||
|
||||
<ImageView
|
||||
android:id="@+id/pageIcon"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_gravity="center"
|
||||
android:contentDescription="@string/content_description_page_icon" />
|
||||
|
||||
<ImageView
|
||||
android:id="@+id/linkImage"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="match_parent" />
|
||||
|
||||
<ImageView
|
||||
android:id="@+id/linkEmoji"
|
||||
android:layout_width="20dp"
|
||||
android:layout_height="20dp"
|
||||
android:layout_gravity="center" />
|
||||
|
||||
</FrameLayout>
|
||||
</ImageView>
|
||||
|
||||
<com.anytypeio.anytype.core_ui.widgets.text.TextHighlightWidget
|
||||
android:id="@+id/pageTitle"
|
||||
style="@style/BlockPageArchivedContentStyle"
|
||||
android:layout_width="0dp"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_marginStart="4dp"
|
||||
android:background="@null"
|
||||
android:ellipsize="end"
|
||||
android:maxLines="1"
|
||||
app:layout_constraintBottom_toBottomOf="parent"
|
||||
app:layout_constraintEnd_toEndOf="parent"
|
||||
app:layout_constraintStart_toEndOf="@+id/pageIconContainer"
|
||||
app:layout_constraintStart_toEndOf="@+id/ivIcon"
|
||||
app:layout_constraintTop_toTopOf="parent"
|
||||
tools:text="Partnership terms Partnership terms Partnership terms Partnership terms" />
|
||||
|
||||
|
|
|
@ -23,34 +23,17 @@
|
|||
android:orientation="vertical"
|
||||
app:layout_constraintGuide_begin="0dp" />
|
||||
|
||||
<FrameLayout
|
||||
android:id="@+id/pageIconContainer"
|
||||
android:layout_width="24dp"
|
||||
android:layout_height="24dp"
|
||||
app:layout_constraintBottom_toBottomOf="parent"
|
||||
app:layout_constraintStart_toEndOf="@id/pageGuideline"
|
||||
app:layout_constraintTop_toTopOf="parent">
|
||||
|
||||
<ImageView
|
||||
android:layout_width="20dp"
|
||||
android:layout_height="20dp"
|
||||
android:layout_gravity="center"
|
||||
android:src="@drawable/ic_non_existent_object" />
|
||||
|
||||
</FrameLayout>
|
||||
|
||||
<TextView
|
||||
android:id="@+id/linkDeleteTitle"
|
||||
style="@style/BlockObjectLinkDeleteContentStyle"
|
||||
android:layout_width="0dp"
|
||||
android:layout_height="wrap_content"
|
||||
android:background="@null"
|
||||
android:text="@string/non_existent_object"
|
||||
android:text="@string/deleted_object"
|
||||
app:layout_constraintBottom_toBottomOf="parent"
|
||||
app:layout_constraintEnd_toEndOf="parent"
|
||||
app:layout_constraintStart_toEndOf="@+id/pageIconContainer"
|
||||
app:layout_constraintTop_toTopOf="parent"
|
||||
tools:text="Non-existent object" />
|
||||
app:layout_constraintStart_toEndOf="@id/pageGuideline"
|
||||
app:layout_constraintTop_toTopOf="parent" />
|
||||
|
||||
</androidx.constraintlayout.widget.ConstraintLayout>
|
||||
</FrameLayout>
|
|
@ -1,22 +1,29 @@
|
|||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<FrameLayout xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
xmlns:tools="http://schemas.android.com/tools"
|
||||
style="@style/DefaultDocumentContainerStyle"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content">
|
||||
android:layout_height="wrap_content"
|
||||
android:paddingStart="@dimen/dp_8"
|
||||
android:paddingEnd="8dp"
|
||||
tools:context="com.anytypeio.anytype.core_ui.features.editor.holders.other.LinkToObjectLoading">
|
||||
|
||||
<LinearLayout
|
||||
android:id="@+id/container"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:background="@drawable/item_block_multi_select_mode_selector"
|
||||
android:orientation="horizontal"
|
||||
android:paddingStart="@dimen/default_document_content_padding_start"
|
||||
android:paddingEnd="@dimen/default_document_content_padding_end">
|
||||
android:paddingEnd="@dimen/default_document_content_padding_end"
|
||||
tools:background="@drawable/item_block_multi_select_selected">
|
||||
|
||||
<ProgressBar
|
||||
android:id="@+id/progress"
|
||||
android:layout_width="20dp"
|
||||
android:layout_height="20dp"
|
||||
android:layout_width="24dp"
|
||||
android:layout_height="24dp"
|
||||
android:layout_gravity="center_vertical"
|
||||
android:theme="@style/GreyProgressBar" />
|
||||
android:theme="@style/SyncingObjectStyle" />
|
||||
|
||||
<TextView
|
||||
android:id="@+id/syncing"
|
||||
|
@ -24,6 +31,6 @@
|
|||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:text="@string/syncing"
|
||||
android:textColor="#ACA996" />
|
||||
android:textColor="@color/text_tertiary" />
|
||||
</LinearLayout>
|
||||
</FrameLayout>
|
|
@ -224,6 +224,7 @@
|
|||
<dimen name="default_graphic_text_text_padding_bottom">4dp</dimen>
|
||||
<dimen name="default_graphic_text_graphic_margin_top">5dp</dimen>
|
||||
<dimen name="default_graphic_text_graphic_width">24dp</dimen>
|
||||
<dimen name="default_graphic_text_text_first_line_margin_start">28dp</dimen>
|
||||
|
||||
<!-- Editor, block: media placeholder -->
|
||||
<dimen name="default_media_placeholder_root_margin_top">10dp</dimen>
|
||||
|
|
|
@ -482,6 +482,7 @@
|
|||
<string name="name_type_page_icon">📄</string>
|
||||
<string name="name_type_page_subtitle">Proto type to start with</string>
|
||||
<string name="non_existent_object">Non-existent object</string>
|
||||
<string name="deleted_object">Deleted object</string>
|
||||
<string name="open_set">Open set</string>
|
||||
<string name="deleted">Deleted</string>
|
||||
<string name="paste_link_or_search">Paste link or search objects</string>
|
||||
|
|
|
@ -100,18 +100,15 @@
|
|||
<item name="android:fontFamily">@font/inter_regular</item>
|
||||
</style>
|
||||
|
||||
<style name="BlockObjectLinkDeleteContentStyle" parent="BlockPageContentStyle">
|
||||
<item name="android:textColor">#CBC9BD</item>
|
||||
<style name="BlockObjectLinkDeleteContentStyle">
|
||||
<item name="android:textColor">@color/text_tertiary</item>
|
||||
<item name="android:textSize">17sp</item>
|
||||
<item name="android:fontFamily">@font/inter_regular</item>
|
||||
</style>
|
||||
|
||||
<style name="BlockPageArchivedContentStyle">
|
||||
<item name="android:layout_marginStart">4dp</item>
|
||||
<item name="android:fontFamily">@font/inter_regular</item>
|
||||
<item name="android:paddingTop">3dp</item>
|
||||
<item name="android:paddingBottom">3dp</item>
|
||||
<item name="android:textColor">@color/text_secondary</item>
|
||||
<item name="android:textColor">@color/text_tertiary</item>
|
||||
<item name="android:textSize">17sp</item>
|
||||
</style>
|
||||
|
||||
|
@ -324,6 +321,10 @@
|
|||
<item name="colorAccent">@color/text_secondary</item>
|
||||
</style>
|
||||
|
||||
<style name="SyncingObjectStyle" parent="ThemeOverlay.AppCompat.Light">
|
||||
<item name="colorAccent">@color/text_tertiary</item>
|
||||
</style>
|
||||
|
||||
<style name="WhiteProgressBar" parent="ThemeOverlay.AppCompat.Light">
|
||||
<item name="colorAccent">@color/white</item>
|
||||
</style>
|
||||
|
@ -1040,4 +1041,21 @@
|
|||
<item name="android:lineSpacingMultiplier">1.1</item>
|
||||
</style>
|
||||
|
||||
<!-- Editor, object link as text block, {root {guideline , iconObjectContainer, text, tvObjectType, tvDescription}}-->
|
||||
<style name="ObjectLinkBlockTextStyle">
|
||||
<item name="android:background">@null</item>
|
||||
<item name="android:fontFamily">@font/inter_medium</item>
|
||||
<item name="android:textColor">@color/text_primary</item>
|
||||
<item name="android:textSize">17sp</item>
|
||||
<item name="lineHeight">22sp</item>
|
||||
</style>
|
||||
|
||||
<style name="ObjectLinkBlockRelationsStyle">
|
||||
<item name="android:background">@null</item>
|
||||
<item name="android:fontFamily">@font/inter_regular</item>
|
||||
<item name="android:textColor">@color/text_secondary</item>
|
||||
<item name="android:textSize">12sp</item>
|
||||
</style>
|
||||
|
||||
|
||||
</resources>
|
|
@ -11,7 +11,7 @@ android {
|
|||
minSdkVersion config["min_sdk"]
|
||||
targetSdkVersion config["target_sdk"]
|
||||
testInstrumentationRunner config["test_runner"]
|
||||
buildConfigField "boolean", "ENABLE_LINK_APPERANCE_MENU", "false"
|
||||
buildConfigField "boolean", "ENABLE_LINK_APPERANCE_MENU", "true"
|
||||
buildConfigField "boolean", "NESTED_DECORATION_ENABLED", "true"
|
||||
}
|
||||
|
||||
|
|
|
@ -3552,8 +3552,6 @@ class EditorViewModel(
|
|||
}
|
||||
is ListenerType.LinkToObjectArchived -> {
|
||||
when (mode) {
|
||||
EditorMode.Edit -> onPageClicked(clicked.target)
|
||||
EditorMode.Locked -> onPageClicked(clicked.target)
|
||||
EditorMode.Select -> onBlockMultiSelectClicked(clicked.target)
|
||||
else -> Unit
|
||||
}
|
||||
|
@ -3565,6 +3563,13 @@ class EditorViewModel(
|
|||
else -> Unit
|
||||
}
|
||||
}
|
||||
is ListenerType.LinkToObjectLoading -> {
|
||||
when (mode) {
|
||||
EditorMode.Edit -> Unit
|
||||
EditorMode.Select -> onBlockMultiSelectClicked(clicked.target)
|
||||
else -> Unit
|
||||
}
|
||||
}
|
||||
is ListenerType.Mention -> {
|
||||
when (mode) {
|
||||
EditorMode.Edit, EditorMode.Locked -> {
|
||||
|
|
|
@ -325,6 +325,9 @@ fun List<BlockView>.enterSAM(
|
|||
is BlockView.LinkToObject.Deleted -> view.copy(
|
||||
isSelected = isSelected
|
||||
)
|
||||
is BlockView.LinkToObject.Loading -> view.copy(
|
||||
isSelected = isSelected
|
||||
)
|
||||
is BlockView.DividerDots -> view.copy(
|
||||
isSelected = isSelected
|
||||
)
|
||||
|
@ -881,6 +884,7 @@ fun BlockView.updateSelection(newSelection: Boolean) = when (this) {
|
|||
is BlockView.LinkToObject.Default.Card -> copy(isSelected = newSelection)
|
||||
is BlockView.LinkToObject.Archived -> copy(isSelected = newSelection)
|
||||
is BlockView.LinkToObject.Deleted -> copy(isSelected = newSelection)
|
||||
is BlockView.LinkToObject.Loading -> copy(isSelected = newSelection)
|
||||
is BlockView.MediaPlaceholder.Bookmark -> copy(isSelected = newSelection)
|
||||
is BlockView.Media.Bookmark -> copy(isSelected = newSelection)
|
||||
is BlockView.Error.Bookmark -> copy(isSelected = newSelection)
|
||||
|
|
|
@ -53,6 +53,7 @@ sealed interface ListenerType {
|
|||
data class LinkToObject(val target: String) : ListenerType
|
||||
data class LinkToObjectArchived(val target: String) : ListenerType
|
||||
data class LinkToObjectDeleted(val target: String) : ListenerType
|
||||
data class LinkToObjectLoading(val target: String) : ListenerType
|
||||
|
||||
data class Mention(val target: String) : ListenerType
|
||||
|
||||
|
|
|
@ -61,6 +61,8 @@ import com.anytypeio.anytype.presentation.editor.editor.model.types.Types.HOLDER
|
|||
import com.anytypeio.anytype.presentation.editor.editor.model.types.Types.HOLDER_VIDEO_PLACEHOLDER
|
||||
import com.anytypeio.anytype.presentation.editor.editor.model.types.Types.HOLDER_VIDEO_UPLOAD
|
||||
import com.anytypeio.anytype.presentation.objects.ObjectIcon
|
||||
import com.anytypeio.anytype.presentation.objects.appearance.choose.ObjectAppearanceChooseIconViewModel
|
||||
import com.anytypeio.anytype.presentation.objects.appearance.choose.ObjectAppearanceChooseSettingsView
|
||||
import com.anytypeio.anytype.presentation.relations.DocumentRelationView
|
||||
|
||||
/**
|
||||
|
@ -244,6 +246,7 @@ sealed class BlockView : ViewType {
|
|||
data class Menu(
|
||||
val preview: MenuItem.PreviewLayout,
|
||||
val icon: MenuItem.Icon?,
|
||||
val iconMenus: List<ObjectAppearanceChooseSettingsView.Icon>,
|
||||
val cover: MenuItem.Cover?,
|
||||
val description: MenuItem.Description?,
|
||||
val objectType: MenuItem.ObjectType,
|
||||
|
@ -1056,6 +1059,7 @@ sealed class BlockView : ViewType {
|
|||
abstract val description: String?
|
||||
abstract val icon: ObjectIcon
|
||||
abstract val background: ThemeColor
|
||||
abstract val objectTypeName: String?
|
||||
|
||||
data class Text(
|
||||
override val id: String,
|
||||
|
@ -1066,7 +1070,8 @@ sealed class BlockView : ViewType {
|
|||
override val description: String? = null,
|
||||
override val icon: ObjectIcon,
|
||||
override val background: ThemeColor = ThemeColor.DEFAULT,
|
||||
override val decorations: List<Decoration> = emptyList()
|
||||
override val decorations: List<Decoration> = emptyList(),
|
||||
override val objectTypeName: String? = null
|
||||
) : Default(), Searchable {
|
||||
override fun getViewType() = HOLDER_OBJECT_LINK_DEFAULT
|
||||
}
|
||||
|
@ -1081,7 +1086,7 @@ sealed class BlockView : ViewType {
|
|||
override val icon: ObjectIcon,
|
||||
override val background: ThemeColor,
|
||||
override val decorations: List<Decoration> = emptyList(),
|
||||
val objectTypeName: String?,
|
||||
override val objectTypeName: String? = null,
|
||||
val coverColor: CoverColor? = null,
|
||||
val coverImage: Url? = null,
|
||||
val coverGradient: String? = null,
|
||||
|
|
|
@ -1203,7 +1203,7 @@ class DefaultBlockViewRenderer @Inject constructor(
|
|||
isPreviousBlockMedia: Boolean,
|
||||
schema: NestedDecorationData,
|
||||
details: Block.Details
|
||||
): BlockView = when(content.state) {
|
||||
): BlockView = when (content.state) {
|
||||
Content.Bookmark.State.EMPTY -> {
|
||||
BlockView.MediaPlaceholder.Bookmark(
|
||||
id = block.id,
|
||||
|
@ -1651,7 +1651,7 @@ class DefaultBlockViewRenderer @Inject constructor(
|
|||
val inEditorAppearance = factory.createInEditorLinkAppearance()
|
||||
val isCard = inEditorAppearance.isCard
|
||||
val icon = if (inEditorAppearance.showIcon) {
|
||||
ObjectIcon.from(
|
||||
ObjectIcon.getEditorLinkToObjectIcon(
|
||||
obj = obj,
|
||||
layout = obj.layout,
|
||||
builder = urlBuilder
|
||||
|
@ -1661,25 +1661,26 @@ class DefaultBlockViewRenderer @Inject constructor(
|
|||
}
|
||||
val name = obj.getProperObjectName()
|
||||
|
||||
val description = when (inEditorAppearance.description) {
|
||||
InEditor.Description.NONE -> null
|
||||
InEditor.Description.RELATION -> obj.description
|
||||
InEditor.Description.SNIPPET -> obj.snippet
|
||||
}
|
||||
val objectTypeName = if (inEditorAppearance.showType) {
|
||||
val typeUrl = obj.type.firstOrNull()
|
||||
objectTypes.find { it.url == typeUrl }?.name
|
||||
} else {
|
||||
null
|
||||
}
|
||||
|
||||
return if (isCard) {
|
||||
val description = when (inEditorAppearance.description) {
|
||||
InEditor.Description.NONE -> null
|
||||
InEditor.Description.RELATION -> obj.description
|
||||
InEditor.Description.SNIPPET -> obj.snippet
|
||||
}
|
||||
val type = if (inEditorAppearance.showType) {
|
||||
val typeUrl = obj.type.firstOrNull()
|
||||
objectTypes.find { it.url == typeUrl }?.name
|
||||
} else {
|
||||
null
|
||||
}
|
||||
|
||||
var coverColor: CoverColor? = null
|
||||
var coverImage: Url? = null
|
||||
var coverGradient: String? = null
|
||||
|
||||
if (inEditorAppearance.showCover) {
|
||||
when (val type = obj.coverType) {
|
||||
when (obj.coverType) {
|
||||
CoverType.UPLOADED_IMAGE -> {
|
||||
coverImage = obj.coverId?.let { id ->
|
||||
urlBuilder.image(id)
|
||||
|
@ -1699,7 +1700,7 @@ class DefaultBlockViewRenderer @Inject constructor(
|
|||
CoverType.GRADIENT -> {
|
||||
coverGradient = obj.coverId
|
||||
}
|
||||
else -> Timber.d("Missing cover type: $type")
|
||||
else -> Timber.d("Missing cover type: ${obj.coverType?.name}")
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -1719,7 +1720,7 @@ class DefaultBlockViewRenderer @Inject constructor(
|
|||
coverGradient = coverGradient,
|
||||
background = block.parseThemeBackgroundColor(),
|
||||
isPreviousBlockMedia = isPreviousBlockMedia,
|
||||
objectTypeName = type,
|
||||
objectTypeName = objectTypeName,
|
||||
decorations = buildNestedDecorationData(
|
||||
block = block,
|
||||
parentScheme = parentSchema,
|
||||
|
@ -1748,7 +1749,9 @@ class DefaultBlockViewRenderer @Inject constructor(
|
|||
style = DecorationData.Style.None,
|
||||
background = block.parseThemeBackgroundColor()
|
||||
)
|
||||
).toBlockViewDecoration(block)
|
||||
).toBlockViewDecoration(block),
|
||||
description = description,
|
||||
objectTypeName = objectTypeName
|
||||
)
|
||||
}
|
||||
}
|
||||
|
@ -1763,15 +1766,8 @@ class DefaultBlockViewRenderer @Inject constructor(
|
|||
): BlockView.LinkToObject.Archived = BlockView.LinkToObject.Archived(
|
||||
id = block.id,
|
||||
isEmpty = true,
|
||||
emoji = obj.iconEmoji?.let { name ->
|
||||
name.ifEmpty { null }
|
||||
},
|
||||
image = obj.iconImage?.let { name ->
|
||||
if (name.isNotEmpty())
|
||||
urlBuilder.image(name)
|
||||
else
|
||||
null
|
||||
},
|
||||
emoji = null,
|
||||
image = null,
|
||||
text = obj.getProperObjectName(),
|
||||
indent = indent,
|
||||
isSelected = checkIfSelected(
|
||||
|
|
|
@ -74,5 +74,56 @@ sealed class ObjectIcon {
|
|||
null -> None
|
||||
}
|
||||
}
|
||||
|
||||
fun getEditorLinkToObjectIcon(
|
||||
obj: ObjectWrapper.Basic,
|
||||
layout: ObjectType.Layout?,
|
||||
builder: UrlBuilder
|
||||
): ObjectIcon {
|
||||
val img = obj.iconImage
|
||||
val emoji = obj.iconEmoji
|
||||
return when (layout) {
|
||||
ObjectType.Layout.BASIC -> when {
|
||||
!img.isNullOrBlank() -> Basic.Image(hash = builder.thumbnail(img))
|
||||
!emoji.isNullOrBlank() -> Basic.Emoji(unicode = emoji)
|
||||
else -> None
|
||||
}
|
||||
ObjectType.Layout.OBJECT_TYPE -> when {
|
||||
!img.isNullOrBlank() -> Basic.Image(hash = builder.thumbnail(img))
|
||||
!emoji.isNullOrBlank() -> Basic.Emoji(unicode = emoji)
|
||||
else -> Basic.Avatar(obj.name.orEmpty())
|
||||
}
|
||||
ObjectType.Layout.PROFILE -> if (!img.isNullOrBlank()) {
|
||||
Profile.Image(hash = builder.thumbnail(img))
|
||||
} else {
|
||||
Profile.Avatar(name = obj.name.orEmpty())
|
||||
}
|
||||
ObjectType.Layout.SET -> if (!img.isNullOrBlank()) {
|
||||
Basic.Image(hash = builder.thumbnail(img))
|
||||
} else if (!emoji.isNullOrBlank()) {
|
||||
Basic.Emoji(unicode = emoji)
|
||||
} else {
|
||||
None
|
||||
}
|
||||
ObjectType.Layout.IMAGE -> if (!img.isNullOrBlank()) {
|
||||
Basic.Image(hash = builder.thumbnail(img))
|
||||
} else {
|
||||
None
|
||||
}
|
||||
ObjectType.Layout.TODO -> Task(isChecked = obj.done ?: false)
|
||||
ObjectType.Layout.NOTE -> Basic.Avatar(obj.snippet.orEmpty())
|
||||
ObjectType.Layout.FILE -> Basic.Avatar(obj.name.orEmpty())
|
||||
ObjectType.Layout.BOOKMARK -> when {
|
||||
!img.isNullOrBlank() -> Bookmark(image = builder.thumbnail(img))
|
||||
!emoji.isNullOrBlank() -> Basic.Emoji(unicode = emoji)
|
||||
else -> None
|
||||
}
|
||||
ObjectType.Layout.RELATION -> None
|
||||
ObjectType.Layout.DASHBOARD -> None
|
||||
ObjectType.Layout.SPACE -> None
|
||||
ObjectType.Layout.DATABASE -> None
|
||||
null -> None
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
|
@ -7,6 +7,7 @@ import com.anytypeio.anytype.core_models.ObjectType
|
|||
import com.anytypeio.anytype.presentation.editor.editor.model.BlockView
|
||||
import com.anytypeio.anytype.presentation.editor.editor.model.BlockView.Appearance.InEditor
|
||||
import com.anytypeio.anytype.presentation.editor.editor.model.BlockView.Appearance.MenuItem
|
||||
import com.anytypeio.anytype.presentation.objects.appearance.choose.ObjectAppearanceChooseSettingsView
|
||||
|
||||
internal class LinkAppearanceFactory(
|
||||
private val content: Block.Content.Link,
|
||||
|
@ -15,7 +16,7 @@ internal class LinkAppearanceFactory(
|
|||
|
||||
private val isTodoLayout = layout == ObjectType.Layout.TODO
|
||||
private val isNoteLayout = layout == ObjectType.Layout.NOTE
|
||||
private val withDescription = content.cardStyle != CardStyle.TEXT && !isNoteLayout
|
||||
private val withDescription = !isNoteLayout
|
||||
|
||||
//todo Cover menu option is off. No proper design yet.
|
||||
private val canHaveCover: Boolean =
|
||||
|
@ -31,7 +32,7 @@ internal class LinkAppearanceFactory(
|
|||
}
|
||||
val description = when {
|
||||
!withDescription -> InEditor.Description.NONE
|
||||
else -> when(content.description) {
|
||||
else -> when (content.description) {
|
||||
Block.Content.Link.Description.NONE -> InEditor.Description.NONE
|
||||
Block.Content.Link.Description.ADDED -> InEditor.Description.RELATION
|
||||
Block.Content.Link.Description.CONTENT -> InEditor.Description.SNIPPET
|
||||
|
@ -61,6 +62,24 @@ internal class LinkAppearanceFactory(
|
|||
IconSize.MEDIUM -> MenuItem.Icon.MEDIUM
|
||||
}
|
||||
} else null
|
||||
val iconMenus = if (hasIconMenuItem) {
|
||||
when (preview) {
|
||||
MenuItem.PreviewLayout.CARD -> {
|
||||
listOf(
|
||||
ObjectAppearanceChooseSettingsView.Icon.None(isSelected = content.iconSize == IconSize.NONE),
|
||||
ObjectAppearanceChooseSettingsView.Icon.Small(isSelected = content.iconSize == IconSize.SMALL),
|
||||
ObjectAppearanceChooseSettingsView.Icon.Medium(isSelected = content.iconSize == IconSize.MEDIUM)
|
||||
)
|
||||
}
|
||||
MenuItem.PreviewLayout.TEXT -> {
|
||||
listOf(
|
||||
ObjectAppearanceChooseSettingsView.Icon.None(isSelected = content.iconSize == IconSize.NONE),
|
||||
ObjectAppearanceChooseSettingsView.Icon.Small(isSelected = content.iconSize == IconSize.SMALL)
|
||||
)
|
||||
}
|
||||
MenuItem.PreviewLayout.INLINE -> emptyList()
|
||||
}
|
||||
} else emptyList()
|
||||
val cover = if (canHaveCover) {
|
||||
when (withCover) {
|
||||
true -> MenuItem.Cover.WITH
|
||||
|
@ -84,7 +103,8 @@ internal class LinkAppearanceFactory(
|
|||
icon = icon,
|
||||
cover = cover,
|
||||
description = description,
|
||||
objectType,
|
||||
objectType = objectType,
|
||||
iconMenus = iconMenus
|
||||
)
|
||||
}
|
||||
}
|
|
@ -18,12 +18,7 @@ class ObjectAppearanceChooseIconViewModel(
|
|||
storage, setLinkAppearance, dispatcher
|
||||
) {
|
||||
override fun getItems(menu: BlockView.Appearance.Menu): List<Icon> {
|
||||
val iconState = menu.icon
|
||||
return listOf(
|
||||
Icon.None(isSelected = iconState == BlockView.Appearance.MenuItem.Icon.NONE),
|
||||
Icon.Small(isSelected = iconState == BlockView.Appearance.MenuItem.Icon.SMALL),
|
||||
Icon.Medium(isSelected = iconState == BlockView.Appearance.MenuItem.Icon.MEDIUM)
|
||||
)
|
||||
return menu.iconMenus
|
||||
}
|
||||
|
||||
override fun updateAppearance(
|
||||
|
|
|
@ -309,7 +309,7 @@ class EditorLockPageTest : EditorPresentationTestSetup() {
|
|||
),
|
||||
BlockView.LinkToObject.Default.Text(
|
||||
id = link.id,
|
||||
icon = ObjectIcon.Basic.Avatar(""),
|
||||
icon = ObjectIcon.None,
|
||||
decorations = if (BuildConfig.NESTED_DECORATION_ENABLED) {
|
||||
listOf(
|
||||
BlockView.Decoration(
|
||||
|
|
|
@ -142,7 +142,7 @@ class LinkAppearanceInEditorTest {
|
|||
}
|
||||
|
||||
@Test
|
||||
fun `when card style text - no description`() {
|
||||
fun `when card style text - relatoin description`() {
|
||||
val factory = LinkAppearanceFactory(
|
||||
content = defaultLinkAppearance.copy(
|
||||
cardStyle = Link.CardStyle.TEXT,
|
||||
|
@ -156,13 +156,37 @@ class LinkAppearanceInEditorTest {
|
|||
val expected = BlockView.Appearance.InEditor(
|
||||
isCard = false,
|
||||
showIcon = false,
|
||||
description = Description.NONE,
|
||||
description = Description.RELATION,
|
||||
showCover = false,
|
||||
showType = false,
|
||||
)
|
||||
|
||||
assertEquals(expected, actual)
|
||||
}
|
||||
|
||||
@Test
|
||||
fun `when card style text - snippet description`() {
|
||||
val factory = LinkAppearanceFactory(
|
||||
content = defaultLinkAppearance.copy(
|
||||
cardStyle = Link.CardStyle.TEXT,
|
||||
description = Link.Description.CONTENT
|
||||
),
|
||||
layout = ObjectType.Layout.BASIC
|
||||
)
|
||||
|
||||
val actual = factory.createInEditorLinkAppearance()
|
||||
|
||||
val expected = BlockView.Appearance.InEditor(
|
||||
isCard = false,
|
||||
showIcon = false,
|
||||
description = Description.SNIPPET,
|
||||
showCover = false,
|
||||
showType = false,
|
||||
)
|
||||
|
||||
assertEquals(expected, actual)
|
||||
}
|
||||
|
||||
@Test
|
||||
fun `when card style card - there is description`() {
|
||||
val factory = LinkAppearanceFactory(
|
||||
|
|
|
@ -5,6 +5,8 @@ import com.anytypeio.anytype.core_models.ObjectType
|
|||
import com.anytypeio.anytype.presentation.MockBlockContentFactory.StubLinkContent
|
||||
import com.anytypeio.anytype.presentation.editor.editor.model.BlockView
|
||||
import com.anytypeio.anytype.presentation.editor.editor.model.BlockView.Appearance.MenuItem
|
||||
import com.anytypeio.anytype.presentation.objects.appearance.choose.ObjectAppearanceChooseIconViewModel
|
||||
import com.anytypeio.anytype.presentation.objects.appearance.choose.ObjectAppearanceChooseSettingsView
|
||||
import org.junit.Test
|
||||
import kotlin.test.assertEquals
|
||||
|
||||
|
@ -29,8 +31,12 @@ class LinkAppearanceMenuTest {
|
|||
preview = MenuItem.PreviewLayout.TEXT,
|
||||
icon = MenuItem.Icon.SMALL,
|
||||
cover = null,
|
||||
description = null,
|
||||
description = MenuItem.Description.NONE,
|
||||
objectType = MenuItem.ObjectType.WITHOUT,
|
||||
iconMenus = listOf(
|
||||
ObjectAppearanceChooseSettingsView.Icon.None(false),
|
||||
ObjectAppearanceChooseSettingsView.Icon.Small(true)
|
||||
)
|
||||
)
|
||||
assertEquals(expected, actual)
|
||||
}
|
||||
|
@ -47,8 +53,9 @@ class LinkAppearanceMenuTest {
|
|||
preview = MenuItem.PreviewLayout.TEXT,
|
||||
icon = null,
|
||||
cover = null,
|
||||
description = null,
|
||||
description = MenuItem.Description.NONE,
|
||||
objectType = MenuItem.ObjectType.WITHOUT,
|
||||
iconMenus = listOf()
|
||||
)
|
||||
assertEquals(expected, actual)
|
||||
}
|
||||
|
@ -69,6 +76,7 @@ class LinkAppearanceMenuTest {
|
|||
cover = null,
|
||||
description = null,
|
||||
objectType = MenuItem.ObjectType.WITHOUT,
|
||||
iconMenus = listOf()
|
||||
)
|
||||
assertEquals(expected, actual)
|
||||
}
|
||||
|
@ -90,6 +98,11 @@ class LinkAppearanceMenuTest {
|
|||
cover = null,
|
||||
description = MenuItem.Description.ADDED,
|
||||
objectType = MenuItem.ObjectType.WITHOUT,
|
||||
iconMenus = listOf(
|
||||
ObjectAppearanceChooseSettingsView.Icon.None(false),
|
||||
ObjectAppearanceChooseSettingsView.Icon.Small(true),
|
||||
ObjectAppearanceChooseSettingsView.Icon.Medium(false)
|
||||
)
|
||||
)
|
||||
assertEquals(expected, actual)
|
||||
}
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue