mirror of
https://github.com/anyproto/anytype-kotlin.git
synced 2025-06-08 05:47:05 +09:00
DRAFT-718 Editor | Enhancement | Inline set block (#2864)
* DROID-718 Editor | Enhancement | Inline set block (#2813) * DROID-718 data view blocks, xml * DROID-718 add content description * DROID-718 data view holders * DROID-718 add holders to editor adapter * DROID-718 blockview, data view * DROID-718 block data view, mapping * DROID-718 target object id * DROID-718 target object id mapping * DROID-718 design fix * DROID-718 fix * DROID-718 add default value * DROID-718 fixes * DROID-718 rename * DROID-718 pr fix * DROID-794 Editor | Enhancement | Inline set, open source icon (#2830) * DROID-794 open source icon added * DROID-794 fix toast * DROID-794 refactoring * DROID-718 Editor | Enhancement | Set View, fixes (#2834) * DROID-718 rename Inline set -> Set View * DROID-718 set view blocks ui fixes * DROID-718 legacy * DROID-718 legacy * DROID-718 pr fix * DROID-718 Editor | Fix | Rename to inline sets (#2863) * test fix
This commit is contained in:
parent
d94b07a338
commit
d670823b7a
21 changed files with 885 additions and 27 deletions
|
@ -288,7 +288,8 @@ data class Block(
|
|||
val viewers: List<Viewer>,
|
||||
@Deprecated("To be deleted")
|
||||
val relations: List<Relation>,
|
||||
val relationsIndex: List<RelationLink> = emptyList()
|
||||
val relationsIndex: List<RelationLink> = emptyList(),
|
||||
val targetObjectId: Id = "",
|
||||
) : Content() {
|
||||
|
||||
data class Viewer(
|
||||
|
|
|
@ -21,6 +21,9 @@ import com.anytypeio.anytype.core_ui.databinding.ItemBlockBulletedBinding
|
|||
import com.anytypeio.anytype.core_ui.databinding.ItemBlockCalloutBinding
|
||||
import com.anytypeio.anytype.core_ui.databinding.ItemBlockCheckboxBinding
|
||||
import com.anytypeio.anytype.core_ui.databinding.ItemBlockCodeSnippetBinding
|
||||
import com.anytypeio.anytype.core_ui.databinding.ItemBlockDataViewDefaultBinding
|
||||
import com.anytypeio.anytype.core_ui.databinding.ItemBlockDataViewEmptyDataBinding
|
||||
import com.anytypeio.anytype.core_ui.databinding.ItemBlockDataViewEmptySourceBinding
|
||||
import com.anytypeio.anytype.core_ui.databinding.ItemBlockDescriptionBinding
|
||||
import com.anytypeio.anytype.core_ui.databinding.ItemBlockDividerDotsBinding
|
||||
import com.anytypeio.anytype.core_ui.databinding.ItemBlockDividerLineBinding
|
||||
|
@ -67,6 +70,9 @@ import com.anytypeio.anytype.core_ui.databinding.ItemBlockVideoErrorBinding
|
|||
import com.anytypeio.anytype.core_ui.databinding.ItemBlockVideoUploadingBinding
|
||||
import com.anytypeio.anytype.core_ui.features.editor.BlockViewDiffUtil.Payload
|
||||
import com.anytypeio.anytype.core_ui.features.editor.decoration.DecoratableViewHolder
|
||||
import com.anytypeio.anytype.core_ui.features.editor.holders.dataview.DataViewBlockDefaultHolder
|
||||
import com.anytypeio.anytype.core_ui.features.editor.holders.dataview.DataViewBlockEmptyDataHolder
|
||||
import com.anytypeio.anytype.core_ui.features.editor.holders.dataview.DataViewBlockEmptySourceHolder
|
||||
import com.anytypeio.anytype.core_ui.features.editor.holders.`interface`.TextHolder
|
||||
import com.anytypeio.anytype.core_ui.features.editor.holders.error.BookmarkError
|
||||
import com.anytypeio.anytype.core_ui.features.editor.holders.error.FileError
|
||||
|
@ -136,6 +142,9 @@ import com.anytypeio.anytype.presentation.editor.editor.model.types.Types.HOLDER
|
|||
import com.anytypeio.anytype.presentation.editor.editor.model.types.Types.HOLDER_CALLOUT
|
||||
import com.anytypeio.anytype.presentation.editor.editor.model.types.Types.HOLDER_CHECKBOX
|
||||
import com.anytypeio.anytype.presentation.editor.editor.model.types.Types.HOLDER_CODE_SNIPPET
|
||||
import com.anytypeio.anytype.presentation.editor.editor.model.types.Types.HOLDER_DATA_VIEW_DEFAULT
|
||||
import com.anytypeio.anytype.presentation.editor.editor.model.types.Types.HOLDER_DATA_VIEW_EMPTY_DATA
|
||||
import com.anytypeio.anytype.presentation.editor.editor.model.types.Types.HOLDER_DATA_VIEW_EMPTY_SOURCE
|
||||
import com.anytypeio.anytype.presentation.editor.editor.model.types.Types.HOLDER_DESCRIPTION
|
||||
import com.anytypeio.anytype.presentation.editor.editor.model.types.Types.HOLDER_DIVIDER_DOTS
|
||||
import com.anytypeio.anytype.presentation.editor.editor.model.types.Types.HOLDER_DIVIDER_LINE
|
||||
|
@ -811,6 +820,21 @@ class BlockAdapter(
|
|||
clipboardInterceptor = clipboardInterceptor,
|
||||
onDragAndDropTrigger = onDragAndDropTrigger
|
||||
)
|
||||
HOLDER_DATA_VIEW_EMPTY_SOURCE -> {
|
||||
DataViewBlockEmptySourceHolder(
|
||||
ItemBlockDataViewEmptySourceBinding.inflate(inflater, parent, false)
|
||||
)
|
||||
}
|
||||
HOLDER_DATA_VIEW_EMPTY_DATA -> {
|
||||
DataViewBlockEmptyDataHolder(
|
||||
ItemBlockDataViewEmptyDataBinding.inflate(inflater, parent, false)
|
||||
)
|
||||
}
|
||||
HOLDER_DATA_VIEW_DEFAULT -> {
|
||||
DataViewBlockDefaultHolder(
|
||||
ItemBlockDataViewDefaultBinding.inflate(inflater, parent, false)
|
||||
)
|
||||
}
|
||||
else -> throw IllegalStateException("Unexpected view type: $viewType")
|
||||
}
|
||||
|
||||
|
@ -1224,6 +1248,24 @@ class BlockAdapter(
|
|||
item = blocks[position] as BlockView.Table
|
||||
)
|
||||
}
|
||||
is DataViewBlockDefaultHolder -> {
|
||||
holder.processChangePayloads(
|
||||
payloads = payloads.typeOf(),
|
||||
item = blocks[position] as BlockView.DataView.Default
|
||||
)
|
||||
}
|
||||
is DataViewBlockEmptySourceHolder -> {
|
||||
holder.processChangePayloads(
|
||||
payloads = payloads.typeOf(),
|
||||
item = blocks[position] as BlockView.DataView.EmptySource
|
||||
)
|
||||
}
|
||||
is DataViewBlockEmptyDataHolder -> {
|
||||
holder.processChangePayloads(
|
||||
payloads = payloads.typeOf(),
|
||||
item = blocks[position] as BlockView.DataView.EmptyData
|
||||
)
|
||||
}
|
||||
else -> throw IllegalStateException("Unexpected view holder: $holder")
|
||||
}
|
||||
checkIfDecorationChanged(holder, payloads.typeOf(), position)
|
||||
|
@ -1544,6 +1586,24 @@ class BlockAdapter(
|
|||
is TableBlockHolder -> {
|
||||
holder.bind(item = blocks[position] as BlockView.Table)
|
||||
}
|
||||
is DataViewBlockEmptySourceHolder -> {
|
||||
holder.bind(
|
||||
item = blocks[position] as BlockView.DataView.EmptySource,
|
||||
clicked = onClickListener
|
||||
)
|
||||
}
|
||||
is DataViewBlockEmptyDataHolder -> {
|
||||
holder.bind(
|
||||
item = blocks[position] as BlockView.DataView.EmptyData,
|
||||
clicked = onClickListener
|
||||
)
|
||||
}
|
||||
is DataViewBlockDefaultHolder -> {
|
||||
holder.bind(
|
||||
item = blocks[position] as BlockView.DataView.Default,
|
||||
clicked = onClickListener
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
if (holder is Text<*>) {
|
||||
|
|
|
@ -259,6 +259,18 @@ class BlockViewDiffUtil(
|
|||
}
|
||||
}
|
||||
|
||||
if (newBlock is BlockView.DataView && oldBlock is BlockView.DataView) {
|
||||
if (newBlock.title != oldBlock.title) {
|
||||
changes.add(DATA_VIEW_TITLE_CHANGED)
|
||||
}
|
||||
if (newBlock.icon != oldBlock.icon) {
|
||||
changes.add(DATA_VIEW_ICON_CHANGED)
|
||||
}
|
||||
if (newBlock.background != oldBlock.background) {
|
||||
changes.add(BACKGROUND_COLOR_CHANGED)
|
||||
}
|
||||
}
|
||||
|
||||
return if (changes.isNotEmpty())
|
||||
Payload(changes).also { Timber.d("Returning payload: $it") }
|
||||
else
|
||||
|
@ -301,6 +313,10 @@ class BlockViewDiffUtil(
|
|||
|
||||
val isCalloutIconChanged: Boolean get() = changes.contains(CALLOUT_ICON_CHANGED)
|
||||
|
||||
val isDataViewTitleChanged : Boolean get() = changes.contains(DATA_VIEW_TITLE_CHANGED)
|
||||
val isDataViewIconChanged : Boolean get() = changes.contains(DATA_VIEW_ICON_CHANGED)
|
||||
val isDataViewBackgroundChanged : Boolean get() = changes.contains(DATA_VIEW_BACKGROUND_CHANGED)
|
||||
|
||||
fun markupChanged() = changes.contains(MARKUP_CHANGED)
|
||||
fun textChanged() = changes.contains(TEXT_CHANGED)
|
||||
fun textColorChanged() = changes.contains(TEXT_COLOR_CHANGED)
|
||||
|
@ -351,5 +367,9 @@ class BlockViewDiffUtil(
|
|||
|
||||
const val TABLE_CELLS_SELECTION_CHANGED = 340
|
||||
const val TABLE_CELLS_CHANGED = 341
|
||||
|
||||
const val DATA_VIEW_TITLE_CHANGED = 350
|
||||
const val DATA_VIEW_ICON_CHANGED = 351
|
||||
const val DATA_VIEW_BACKGROUND_CHANGED = 352
|
||||
}
|
||||
}
|
|
@ -0,0 +1,273 @@
|
|||
package com.anytypeio.anytype.core_ui.features.editor.holders.dataview
|
||||
|
||||
import android.text.Spannable
|
||||
import android.text.SpannableString
|
||||
import android.view.View
|
||||
import android.widget.FrameLayout
|
||||
import android.widget.TextView
|
||||
import androidx.cardview.widget.CardView
|
||||
import androidx.constraintlayout.widget.ConstraintLayout
|
||||
import androidx.core.view.updateLayoutParams
|
||||
import androidx.recyclerview.widget.RecyclerView
|
||||
import com.anytypeio.anytype.core_models.ThemeColor
|
||||
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.databinding.ItemBlockDataViewDefaultBinding
|
||||
import com.anytypeio.anytype.core_ui.databinding.ItemBlockDataViewEmptyDataBinding
|
||||
import com.anytypeio.anytype.core_ui.databinding.ItemBlockDataViewEmptySourceBinding
|
||||
import com.anytypeio.anytype.core_ui.extensions.setBlockBackgroundColor
|
||||
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.DecoratableCardViewHolder
|
||||
import com.anytypeio.anytype.core_ui.features.editor.decoration.EditorDecorationContainer
|
||||
import com.anytypeio.anytype.core_ui.widgets.ObjectIconWidget
|
||||
import com.anytypeio.anytype.core_utils.ext.gone
|
||||
import com.anytypeio.anytype.core_utils.ext.removeSpans
|
||||
import com.anytypeio.anytype.core_utils.ext.visible
|
||||
import com.anytypeio.anytype.presentation.editor.editor.listener.ListenerType
|
||||
import com.anytypeio.anytype.presentation.editor.editor.model.BlockView
|
||||
import com.anytypeio.anytype.presentation.objects.ObjectIcon
|
||||
|
||||
class DataViewBlockEmptySourceHolder(binding: ItemBlockDataViewEmptySourceBinding) :
|
||||
DataViewBlockViewHolder(binding.root) {
|
||||
|
||||
override val decoratableContainer: EditorDecorationContainer = binding.decorationContainer
|
||||
override val rootView: View = binding.root
|
||||
override val containerView: ConstraintLayout = binding.containerWithBackground
|
||||
override val objectIconView: ObjectIconWidget = binding.cardIcon
|
||||
override val titleView: TextView = binding.cardName
|
||||
override val descriptionView: TextView = binding.cardDescription
|
||||
override val selectedView: View = binding.selected
|
||||
override val decoratableCard: CardView = binding.card
|
||||
|
||||
init {
|
||||
itemView.setOnTouchListener { v, e -> editorTouchProcessor.process(v, e) }
|
||||
}
|
||||
|
||||
fun bind(
|
||||
item: BlockView.DataView.EmptySource,
|
||||
clicked: (ListenerType) -> Unit
|
||||
) {
|
||||
super.bind(item = item, clicked = clicked)
|
||||
}
|
||||
|
||||
fun processChangePayloads(
|
||||
payloads: List<BlockViewDiffUtil.Payload>,
|
||||
item: BlockView.DataView
|
||||
) {
|
||||
payloads.forEach { payload ->
|
||||
processChangeBasePayloads(payload, item)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
class DataViewBlockEmptyDataHolder(binding: ItemBlockDataViewEmptyDataBinding) :
|
||||
DataViewBlockViewHolder(binding.root) {
|
||||
|
||||
override val decoratableContainer: EditorDecorationContainer = binding.decorationContainer
|
||||
override val rootView: View = binding.root
|
||||
override val containerView: ConstraintLayout = binding.containerWithBackground
|
||||
override val objectIconView: ObjectIconWidget = binding.cardIcon
|
||||
override val titleView: TextView = binding.cardName
|
||||
override val descriptionView: TextView = binding.cardDescription
|
||||
override val selectedView: View = binding.selected
|
||||
override val decoratableCard: CardView = binding.card
|
||||
|
||||
init {
|
||||
itemView.setOnTouchListener { v, e -> editorTouchProcessor.process(v, e) }
|
||||
}
|
||||
|
||||
fun bind(
|
||||
item: BlockView.DataView.EmptyData,
|
||||
clicked: (ListenerType) -> Unit
|
||||
) {
|
||||
super.bind(item = item, clicked = clicked)
|
||||
}
|
||||
|
||||
fun processChangePayloads(
|
||||
payloads: List<BlockViewDiffUtil.Payload>,
|
||||
item: BlockView.DataView
|
||||
) {
|
||||
payloads.forEach { payload ->
|
||||
processChangeBasePayloads(payload, item)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
data class DataViewBlockDefaultHolder(
|
||||
val binding: ItemBlockDataViewDefaultBinding
|
||||
) : DataViewBlockViewHolder(binding.root) {
|
||||
|
||||
override val decoratableContainer: EditorDecorationContainer = binding.decorationContainer
|
||||
override val rootView: View = binding.root
|
||||
override val containerView: ConstraintLayout = binding.containerWithBackground
|
||||
override val objectIconView: ObjectIconWidget = binding.cardIcon
|
||||
override val titleView: TextView = binding.cardName
|
||||
override val descriptionView: TextView = binding.cardDescription
|
||||
override val selectedView: View = binding.selected
|
||||
override val decoratableCard: CardView = binding.card
|
||||
|
||||
init {
|
||||
itemView.setOnTouchListener { v, e -> editorTouchProcessor.process(v, e) }
|
||||
}
|
||||
|
||||
fun bind(
|
||||
item: BlockView.DataView.Default,
|
||||
clicked: (ListenerType) -> Unit
|
||||
) {
|
||||
super.bind(item = item, clicked = clicked)
|
||||
}
|
||||
|
||||
fun processChangePayloads(
|
||||
payloads: List<BlockViewDiffUtil.Payload>,
|
||||
item: BlockView.DataView
|
||||
) {
|
||||
payloads.forEach { payload ->
|
||||
processChangeBasePayloads(payload, item)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
sealed class DataViewBlockViewHolder(
|
||||
view: View
|
||||
) : BlockViewHolder(view),
|
||||
BlockViewHolder.DragAndDropHolder,
|
||||
DecoratableCardViewHolder,
|
||||
SupportCustomTouchProcessor,
|
||||
SupportNesting {
|
||||
|
||||
protected abstract val rootView: View
|
||||
abstract val containerView: ConstraintLayout
|
||||
|
||||
private val untitled = itemView.resources.getString(R.string.untitled_set)
|
||||
abstract val objectIconView: ObjectIconWidget
|
||||
abstract val titleView: TextView
|
||||
abstract val descriptionView: TextView
|
||||
abstract val selectedView: View
|
||||
abstract override val decoratableCard: CardView
|
||||
|
||||
override val editorTouchProcessor = EditorTouchProcessor(
|
||||
fallback = { e -> itemView.onTouchEvent(e) }
|
||||
)
|
||||
|
||||
protected fun bind(
|
||||
item: BlockView.DataView,
|
||||
clicked: (ListenerType) -> Unit
|
||||
) {
|
||||
selected(item)
|
||||
|
||||
applyName(item)
|
||||
|
||||
applyBackground(item.background)
|
||||
|
||||
applySearchHighlight(item)
|
||||
|
||||
applyImageOrEmoji(item)
|
||||
|
||||
itemView.setOnClickListener { clicked(ListenerType.DataViewClick(item.id)) }
|
||||
}
|
||||
|
||||
private fun selected(item: BlockView.DataView) {
|
||||
selectedView.isSelected = item.isSelected
|
||||
}
|
||||
|
||||
private fun applyName(item: BlockView.DataView) {
|
||||
val name = item.title
|
||||
val sb = if (name.isNullOrBlank()) "" else SpannableString(name)
|
||||
titleView.append(sb)
|
||||
}
|
||||
|
||||
private fun applyImageOrEmoji(item: BlockView.DataView) {
|
||||
when (item.icon) {
|
||||
ObjectIcon.None -> {
|
||||
objectIconView.gone()
|
||||
}
|
||||
else -> {
|
||||
objectIconView.visible()
|
||||
objectIconView.setIcon(item.icon)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private fun applySearchHighlight(item: BlockView.Searchable) {
|
||||
item.searchFields.find { it.key == BlockView.Searchable.Field.DEFAULT_SEARCH_FIELD_KEY }
|
||||
?.let { field ->
|
||||
applySearchHighlight(field, titleView)
|
||||
} ?: clearSearchHighlights()
|
||||
}
|
||||
|
||||
private fun applySearchHighlight(field: BlockView.Searchable.Field, input: TextView) {
|
||||
val content = input.text as Spannable
|
||||
content.removeSpans<SearchHighlightSpan>()
|
||||
content.removeSpans<SearchTargetHighlightSpan>()
|
||||
field.highlights.forEach { highlight ->
|
||||
content.setSpan(
|
||||
SearchHighlightSpan(),
|
||||
highlight.first,
|
||||
highlight.last,
|
||||
Spannable.SPAN_EXCLUSIVE_EXCLUSIVE
|
||||
)
|
||||
}
|
||||
if (field.isTargeted) {
|
||||
content.setSpan(
|
||||
SearchTargetHighlightSpan(),
|
||||
field.target.first,
|
||||
field.target.last,
|
||||
Spannable.SPAN_EXCLUSIVE_EXCLUSIVE
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
private fun clearSearchHighlights() {
|
||||
titleView.editableText?.removeSpans<SearchHighlightSpan>()
|
||||
titleView.editableText?.removeSpans<SearchTargetHighlightSpan>()
|
||||
}
|
||||
|
||||
protected fun processChangeBasePayloads(
|
||||
payload: BlockViewDiffUtil.Payload,
|
||||
item: BlockView.DataView
|
||||
) {
|
||||
if (payload.isSelectionChanged) {
|
||||
selected(item)
|
||||
}
|
||||
if (payload.isDataViewTitleChanged) {
|
||||
applyName(item)
|
||||
}
|
||||
if (payload.isDataViewIconChanged) {
|
||||
applyImageOrEmoji(item)
|
||||
}
|
||||
if (payload.isDataViewBackgroundChanged) {
|
||||
applyBackground(item.background)
|
||||
}
|
||||
if (payload.isSearchHighlightChanged) {
|
||||
applySearchHighlight(item)
|
||||
}
|
||||
}
|
||||
|
||||
private fun applyBackground(background: ThemeColor) {
|
||||
containerView.setBlockBackgroundColor(background)
|
||||
}
|
||||
|
||||
override fun applyDecorations(decorations: List<BlockView.Decoration>) {
|
||||
super.applyDecorations(decorations)
|
||||
decoratableContainer.decorate(decorations) { rect ->
|
||||
rootView.updateLayoutParams<RecyclerView.LayoutParams> {
|
||||
topMargin = if (rect.left == 0) {
|
||||
itemView.resources.getDimension(R.dimen.dp_10).toInt()
|
||||
} else {
|
||||
0
|
||||
}
|
||||
}
|
||||
selectedView.updateLayoutParams<FrameLayout.LayoutParams> {
|
||||
val defaultIndentOffset =
|
||||
itemView.resources.getDimension(R.dimen.default_indent).toInt()
|
||||
leftMargin = defaultIndentOffset + rect.left
|
||||
rightMargin = defaultIndentOffset + rect.right
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
6
core-ui/src/main/res/drawable/bg_rect_3_radius.xml
Normal file
6
core-ui/src/main/res/drawable/bg_rect_3_radius.xml
Normal file
|
@ -0,0 +1,6 @@
|
|||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<shape xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
android:shape="rectangle">
|
||||
<solid android:color="@color/shape_tertiary" />
|
||||
<corners android:radius="3dp" />
|
||||
</shape>
|
63
core-ui/src/main/res/layout/item_block_data_view_default.xml
Normal file
63
core-ui/src/main/res/layout/item_block_data_view_default.xml
Normal file
|
@ -0,0 +1,63 @@
|
|||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<FrameLayout xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
xmlns:app="http://schemas.android.com/apk/res-auto"
|
||||
xmlns:tools="http://schemas.android.com/tools"
|
||||
android:id="@+id/root"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="@dimen/block_data_view_height"
|
||||
tools:context="com.anytypeio.anytype.core_ui.features.editor.holders.dataview.DataViewBlockDefaultHolder">
|
||||
|
||||
<com.anytypeio.anytype.core_ui.features.editor.decoration.EditorDecorationContainer
|
||||
android:id="@+id/decorationContainer"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="match_parent" />
|
||||
|
||||
<com.google.android.material.card.MaterialCardView
|
||||
android:id="@+id/card"
|
||||
style="@style/BlockDataViewCardStyle"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content">
|
||||
|
||||
<androidx.constraintlayout.widget.ConstraintLayout
|
||||
android:id="@+id/containerWithBackground"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content">
|
||||
|
||||
<TextView
|
||||
android:id="@+id/cardName"
|
||||
style="@style/BlockDataViewTitleStyle"
|
||||
android:layout_width="0dp"
|
||||
android:layout_height="wrap_content"
|
||||
app:layout_constraintBottom_toTopOf="@+id/cardDescription"
|
||||
app:layout_constraintEnd_toEndOf="parent"
|
||||
app:layout_constraintStart_toEndOf="@+id/cardIcon"
|
||||
app:layout_constraintTop_toTopOf="parent"
|
||||
app:layout_constraintVertical_chainStyle="packed"
|
||||
app:layout_goneMarginStart="@dimen/dp_16"
|
||||
tools:text="Reading List"
|
||||
tools:visibility="visible" />
|
||||
|
||||
<TextView
|
||||
android:id="@+id/cardDescription"
|
||||
style="@style/BlockDataViewSubtitleStyle"
|
||||
android:layout_width="0dp"
|
||||
android:layout_height="wrap_content"
|
||||
android:text="@string/inline_set"
|
||||
app:layout_constraintBottom_toBottomOf="parent"
|
||||
app:layout_constraintEnd_toEndOf="parent"
|
||||
app:layout_constraintStart_toStartOf="parent"
|
||||
app:layout_constraintTop_toBottomOf="@+id/cardName" />
|
||||
|
||||
<com.anytypeio.anytype.core_ui.widgets.ObjectIconWidget
|
||||
android:id="@+id/cardIcon"
|
||||
style="@style/BlockDataViewIconStyle"
|
||||
app:layout_constraintStart_toStartOf="parent"
|
||||
app:layout_constraintTop_toTopOf="parent" />
|
||||
|
||||
</androidx.constraintlayout.widget.ConstraintLayout>
|
||||
</com.google.android.material.card.MaterialCardView>
|
||||
|
||||
<View
|
||||
android:id="@+id/selected"
|
||||
style="@style/BlockSelectionStyle" />
|
||||
</FrameLayout>
|
|
@ -0,0 +1,73 @@
|
|||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<FrameLayout xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
xmlns:app="http://schemas.android.com/apk/res-auto"
|
||||
xmlns:tools="http://schemas.android.com/tools"
|
||||
android:id="@+id/root"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="@dimen/block_data_view_height"
|
||||
tools:context="com.anytypeio.anytype.core_ui.features.editor.holders.dataview.DataViewBlockEmptyDataHolder">
|
||||
|
||||
<com.anytypeio.anytype.core_ui.features.editor.decoration.EditorDecorationContainer
|
||||
android:id="@+id/decorationContainer"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="match_parent" />
|
||||
|
||||
<com.google.android.material.card.MaterialCardView
|
||||
android:id="@+id/card"
|
||||
style="@style/BlockDataViewCardStyle"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content">
|
||||
|
||||
<androidx.constraintlayout.widget.ConstraintLayout
|
||||
android:id="@+id/containerWithBackground"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content">
|
||||
|
||||
<TextView
|
||||
android:id="@+id/cardName"
|
||||
style="@style/BlockDataViewTitleStyle"
|
||||
android:layout_width="0dp"
|
||||
android:layout_height="wrap_content"
|
||||
app:layout_constraintBottom_toTopOf="@+id/cardDescription"
|
||||
app:layout_constraintEnd_toStartOf="@+id/cardInfo"
|
||||
app:layout_constraintStart_toEndOf="@+id/cardIcon"
|
||||
app:layout_constraintTop_toTopOf="parent"
|
||||
app:layout_constraintVertical_chainStyle="packed"
|
||||
app:layout_goneMarginStart="@dimen/dp_16"
|
||||
tools:text="Reading List"
|
||||
tools:visibility="visible" />
|
||||
|
||||
<TextView
|
||||
android:id="@+id/cardDescription"
|
||||
style="@style/BlockDataViewSubtitleStyle"
|
||||
android:layout_width="0dp"
|
||||
android:layout_height="wrap_content"
|
||||
android:text="@string/inline_set"
|
||||
app:layout_constraintBottom_toBottomOf="parent"
|
||||
app:layout_constraintEnd_toEndOf="parent"
|
||||
app:layout_constraintStart_toStartOf="parent"
|
||||
app:layout_constraintTop_toBottomOf="@+id/cardName" />
|
||||
|
||||
<com.anytypeio.anytype.core_ui.widgets.ObjectIconWidget
|
||||
android:id="@+id/cardIcon"
|
||||
style="@style/BlockDataViewIconStyle"
|
||||
app:layout_constraintStart_toStartOf="parent"
|
||||
app:layout_constraintTop_toTopOf="parent" />
|
||||
|
||||
<TextView
|
||||
android:id="@+id/cardInfo"
|
||||
style="@style/BlockDataViewInfoStyle"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:text="@string/no_data"
|
||||
android:contentDescription="@string/block_data_view_content_description_no_data"
|
||||
app:layout_constraintEnd_toEndOf="parent"
|
||||
app:layout_constraintTop_toTopOf="parent" />
|
||||
|
||||
</androidx.constraintlayout.widget.ConstraintLayout>
|
||||
</com.google.android.material.card.MaterialCardView>
|
||||
|
||||
<View
|
||||
android:id="@+id/selected"
|
||||
style="@style/BlockSelectionStyle" />
|
||||
</FrameLayout>
|
|
@ -0,0 +1,73 @@
|
|||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<FrameLayout xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
xmlns:app="http://schemas.android.com/apk/res-auto"
|
||||
xmlns:tools="http://schemas.android.com/tools"
|
||||
android:id="@+id/root"
|
||||
style="@style/BlockDataViewRootStyle"
|
||||
tools:context="com.anytypeio.anytype.core_ui.features.editor.holders.dataview.DataViewBlockEmptySourceHolder">
|
||||
|
||||
<com.anytypeio.anytype.core_ui.features.editor.decoration.EditorDecorationContainer
|
||||
android:id="@+id/decorationContainer"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="match_parent" />
|
||||
|
||||
<com.google.android.material.card.MaterialCardView
|
||||
android:id="@+id/card"
|
||||
style="@style/BlockDataViewCardStyle"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content">
|
||||
|
||||
<androidx.constraintlayout.widget.ConstraintLayout
|
||||
android:id="@+id/containerWithBackground"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content">
|
||||
|
||||
<TextView
|
||||
android:id="@+id/cardName"
|
||||
style="@style/BlockDataViewTitleStyle"
|
||||
android:layout_width="0dp"
|
||||
android:layout_height="wrap_content"
|
||||
app:layout_constraintBottom_toTopOf="@+id/cardDescription"
|
||||
app:layout_constraintEnd_toStartOf="@+id/cardInfo"
|
||||
app:layout_constraintStart_toEndOf="@+id/cardIcon"
|
||||
app:layout_constraintTop_toTopOf="parent"
|
||||
app:layout_constraintVertical_chainStyle="packed"
|
||||
app:layout_goneMarginStart="@dimen/dp_16"
|
||||
tools:text="Is your feature request related to a problem? Please describe."
|
||||
tools:visibility="visible" />
|
||||
|
||||
<TextView
|
||||
android:id="@+id/cardDescription"
|
||||
style="@style/BlockDataViewSubtitleStyle"
|
||||
android:layout_width="0dp"
|
||||
android:layout_height="wrap_content"
|
||||
android:text="@string/inline_set"
|
||||
app:layout_constraintBottom_toBottomOf="parent"
|
||||
app:layout_constraintEnd_toEndOf="parent"
|
||||
app:layout_constraintStart_toStartOf="parent"
|
||||
app:layout_constraintTop_toBottomOf="@+id/cardName" />
|
||||
|
||||
<com.anytypeio.anytype.core_ui.widgets.ObjectIconWidget
|
||||
android:id="@+id/cardIcon"
|
||||
style="@style/BlockDataViewIconStyle"
|
||||
app:layout_constraintStart_toStartOf="parent"
|
||||
app:layout_constraintTop_toTopOf="parent" />
|
||||
|
||||
<TextView
|
||||
android:id="@+id/cardInfo"
|
||||
style="@style/BlockDataViewInfoStyle"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:text="@string/no_source"
|
||||
android:contentDescription="@string/block_data_view_content_description_no_source"
|
||||
app:layout_constraintEnd_toEndOf="parent"
|
||||
app:layout_constraintTop_toTopOf="parent" />
|
||||
|
||||
|
||||
</androidx.constraintlayout.widget.ConstraintLayout>
|
||||
</com.google.android.material.card.MaterialCardView>
|
||||
|
||||
<View
|
||||
android:id="@+id/selected"
|
||||
style="@style/BlockSelectionStyle" />
|
||||
</FrameLayout>
|
|
@ -306,4 +306,6 @@
|
|||
|
||||
<dimen name="featured_relations_text_size">13sp</dimen>
|
||||
|
||||
<dimen name="block_data_view_height">96dp</dimen>
|
||||
|
||||
</resources>
|
|
@ -174,6 +174,7 @@
|
|||
|
||||
|
||||
<string name="untitled">Untitled</string>
|
||||
<string name="untitled_set">Untitled set</string>
|
||||
<string name="archived">Archived</string>
|
||||
|
||||
|
||||
|
@ -487,6 +488,8 @@
|
|||
<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="no_data">No data</string>
|
||||
<string name="no_source">No source</string>
|
||||
<string name="deleted_object">Deleted object</string>
|
||||
<string name="open_set">Open set</string>
|
||||
<string name="deleted">Deleted</string>
|
||||
|
@ -519,6 +522,8 @@
|
|||
<string name="visible">Visible</string>
|
||||
<string name="card">Card</string>
|
||||
<string name="inline">Inline</string>
|
||||
<string name="set_view">Set View</string>
|
||||
<string name="inline_set">Inline set</string>
|
||||
<string name="fit_image">Fit image</string>
|
||||
<string name="image_preview">Image preview</string>
|
||||
<string name="cover">Cover</string>
|
||||
|
@ -563,6 +568,7 @@
|
|||
<string name="simple_tables_widget_tab_row">Row</string>
|
||||
<string name="simple_tables_widget_tab_column">Column</string>
|
||||
<string name="open_object">Open object</string>
|
||||
<string name="open_source">Open source</string>
|
||||
<string name="reload_object_content">Reload object content</string>
|
||||
<string name="open_link">Open link</string>
|
||||
<string name="copy_email">Copy email</string>
|
||||
|
@ -589,6 +595,9 @@
|
|||
<string name="my_types">My types</string>
|
||||
<string name="my_relations">My relations</string>
|
||||
<string name="type_added">Type \"%1$s\" added to your library</string>
|
||||
<string name="block_data_view_content_description_title">The name of the source set of the inline set</string>
|
||||
<string name="block_data_view_content_description_no_source">The inline set has no source</string>
|
||||
<string name="block_data_view_content_description_no_data">The source of the inline set has no type</string>
|
||||
|
||||
<string name="object_search_recently_opened_section_title">Recently opened</string>
|
||||
|
||||
|
|
|
@ -1096,4 +1096,82 @@
|
|||
<item name="android:maxLines">1</item>
|
||||
<item name="android:ellipsize">end</item>
|
||||
</style>
|
||||
|
||||
<!-- Editor, data view block -->
|
||||
<style name="BlockDataViewRootStyle">
|
||||
<item name="android:layout_width">match_parent</item>
|
||||
<item name="android:layout_height">@dimen/block_data_view_height</item>
|
||||
</style>
|
||||
|
||||
<style name="BlockDataViewCardStyle" parent="CardView">
|
||||
<item name="cardCornerRadius">12dp</item>
|
||||
<item name="cardElevation">0dp</item>
|
||||
<item name="rippleColor">@android:color/transparent</item>
|
||||
<item name="strokeColor">@color/background_highlighted</item>
|
||||
<item name="strokeWidth">1dp</item>
|
||||
<item name="android:layout_gravity">center_vertical</item>
|
||||
<item name="android:layout_marginStart">@dimen/dp_12</item>
|
||||
<item name="android:layout_marginEnd">@dimen/dp_12</item>
|
||||
</style>
|
||||
|
||||
<style name="BlockDataViewTitleStyle">
|
||||
<item name="android:fontFamily">@font/inter_bold</item>
|
||||
<item name="android:textColor">@color/text_primary</item>
|
||||
<item name="android:textSize">17sp</item>
|
||||
<item name="android:maxLines">1</item>
|
||||
<item name="android:ellipsize">end</item>
|
||||
<item name="android:layout_marginStart">6dp</item>
|
||||
<item name="android:layout_marginTop">18dp</item>
|
||||
<item name="android:layout_marginEnd">16dp</item>
|
||||
<item name="android:includeFontPadding">false</item>
|
||||
<item name="android:hint">@string/untitled_set</item>
|
||||
<item name="android:textColorHint">@color/text_tertiary</item>
|
||||
<item name="android:contentDescription">@string/block_data_view_content_description_title</item>
|
||||
</style>
|
||||
|
||||
<style name="BlockDataViewSubtitleStyle">
|
||||
<item name="android:fontFamily">@font/inter_regular</item>
|
||||
<item name="android:textColor">@color/text_secondary</item>
|
||||
<item name="android:textSize">12sp</item>
|
||||
<item name="android:maxLines">1</item>
|
||||
<item name="android:ellipsize">end</item>
|
||||
<item name="android:layout_marginStart">16dp</item>
|
||||
<item name="android:layout_marginTop">4dp</item>
|
||||
<item name="android:layout_marginEnd">16dp</item>
|
||||
<item name="android:layout_marginBottom">16dp</item>
|
||||
</style>
|
||||
|
||||
<style name="BlockDataViewInfoStyle">
|
||||
<item name="android:fontFamily">@font/inter_regular</item>
|
||||
<item name="android:textColor">@color/text_secondary</item>
|
||||
<item name="android:textSize">11sp</item>
|
||||
<item name="android:maxLines">1</item>
|
||||
<item name="android:ellipsize">end</item>
|
||||
<item name="android:background">@drawable/bg_rect_3_radius</item>
|
||||
<item name="android:paddingTop">1dp</item>
|
||||
<item name="android:paddingEnd">5dp</item>
|
||||
<item name="android:paddingBottom">1dp</item>
|
||||
<item name="android:paddingStart">5dp</item>
|
||||
<item name="android:layout_marginTop">20dp</item>
|
||||
<item name="android:layout_marginEnd">@dimen/dp_16</item>
|
||||
</style>
|
||||
|
||||
<style name="BlockDataViewIconStyle">
|
||||
<item name="android:layout_width">20dp</item>
|
||||
<item name="android:layout_height">20dp</item>
|
||||
<item name="android:layout_marginStart">16dp</item>
|
||||
<item name="android:layout_marginTop">18dp</item>
|
||||
<item name="checkboxSize">18dp</item>
|
||||
<item name="emojiSize">18dp</item>
|
||||
<item name="imageSize">18dp</item>
|
||||
<item name="initialTextSize">11sp</item>
|
||||
</style>
|
||||
|
||||
<style name="BlockSelectionStyle">
|
||||
<item name="android:layout_width">match_parent</item>
|
||||
<item name="android:layout_height">match_parent</item>
|
||||
<item name="android:background">@drawable/item_block_multi_select_mode_selector</item>
|
||||
</style>
|
||||
<!-- Editor, data view block -->
|
||||
|
||||
</resources>
|
|
@ -354,7 +354,8 @@ fun MBlock.toCoreModelsDataView(): Block.Content.DataView {
|
|||
sources = content.source,
|
||||
viewers = content.views.map { it.toCoreModels() },
|
||||
relations = content.relations.map { it.toCoreModels() },
|
||||
relationsIndex = content.relationLinks.map { it.toCoreModels() }
|
||||
relationsIndex = content.relationLinks.map { it.toCoreModels() },
|
||||
targetObjectId = content.TargetObjectId
|
||||
)
|
||||
}
|
||||
|
||||
|
|
|
@ -3022,12 +3022,27 @@ class EditorViewModel(
|
|||
sendToast("Couldn't find the target of the link")
|
||||
}
|
||||
}
|
||||
is Content.DataView -> {
|
||||
proceedWithOpeningInlineSetTarget(target = content.targetObjectId)
|
||||
}
|
||||
else -> {
|
||||
sendToast("Couldn't find the target of the link")
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private fun proceedWithOpeningInlineSetTarget(target: Id) {
|
||||
if (target.isNotEmpty()) {
|
||||
proceedWithOpeningSet(target)
|
||||
viewModelScope.sendAnalyticsOpenAsObject(
|
||||
analytics = analytics,
|
||||
type = EventsDictionary.Type.dataView
|
||||
)
|
||||
} else {
|
||||
sendToast("This inline set doesn’t have a source.")
|
||||
}
|
||||
}
|
||||
|
||||
private fun proceedWithOpeningObjectByLayout(target: String) {
|
||||
proceedWithClearingFocus()
|
||||
val details = orchestrator.stores.details.current()
|
||||
|
@ -3907,6 +3922,14 @@ class EditorViewModel(
|
|||
else -> Unit
|
||||
}
|
||||
}
|
||||
is ListenerType.DataViewClick -> {
|
||||
when (mode) {
|
||||
EditorMode.Edit -> onPageClicked(blockLinkId = clicked.target)
|
||||
EditorMode.Locked -> onPageClicked(blockLinkId = clicked.target)
|
||||
EditorMode.Select -> onBlockMultiSelectClicked(clicked.target)
|
||||
else -> Unit
|
||||
}
|
||||
}
|
||||
else -> {}
|
||||
}
|
||||
}
|
||||
|
@ -5277,15 +5300,7 @@ class EditorViewModel(
|
|||
onSendBlockActionAnalyticsEvent(EventsDictionary.BlockAction.paste)
|
||||
}
|
||||
ActionItemType.OpenObject -> {
|
||||
val selected = blocks.firstOrNull { currentSelection().contains(it.id) }
|
||||
proceedWithExitingMultiSelectMode()
|
||||
if (selected != null) {
|
||||
proceedWithMultiSelectOpenObjectAction(
|
||||
selected = selected
|
||||
)
|
||||
} else {
|
||||
sendToast("No blocks were selected. Please, try again.")
|
||||
}
|
||||
proceedWithOpeningTargetForCurrentSelection()
|
||||
onSendBlockActionAnalyticsEvent(EventsDictionary.BlockAction.openObject)
|
||||
}
|
||||
else -> {
|
||||
|
@ -5294,19 +5309,27 @@ class EditorViewModel(
|
|||
}
|
||||
}
|
||||
|
||||
private fun proceedWithMultiSelectOpenObjectAction(selected: Block) {
|
||||
when (val content = selected.content) {
|
||||
is Content.Bookmark -> {
|
||||
val target = content.targetObjectId
|
||||
if (target != null) {
|
||||
proceedWithOpeningObject(target)
|
||||
viewModelScope.sendAnalyticsOpenAsObject(
|
||||
analytics = analytics,
|
||||
type = EventsDictionary.Type.bookmark
|
||||
)
|
||||
private fun proceedWithOpeningTargetForCurrentSelection() {
|
||||
val selected = blocks.firstOrNull { currentSelection().contains(it.id) }
|
||||
proceedWithExitingMultiSelectMode()
|
||||
if (selected != null) {
|
||||
when (val content = selected.content) {
|
||||
is Content.Bookmark -> {
|
||||
val target = content.targetObjectId
|
||||
if (target != null) {
|
||||
proceedWithOpeningObject(target)
|
||||
viewModelScope.sendAnalyticsOpenAsObject(
|
||||
analytics = analytics,
|
||||
type = EventsDictionary.Type.bookmark
|
||||
)
|
||||
} else {
|
||||
sendToast("This bookmark doesn’t have a source.")
|
||||
}
|
||||
}
|
||||
else -> sendToast("Unexpected object")
|
||||
}
|
||||
else -> sendToast("Unexpected object")
|
||||
} else {
|
||||
sendToast("No blocks were selected. Please, try again.")
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -359,6 +359,15 @@ fun List<BlockView>.enterSAM(
|
|||
isSelected = isSelected,
|
||||
cells = view.cells.updateCellsMode(mode = BlockView.Mode.READ),
|
||||
)
|
||||
is BlockView.DataView.Default -> view.copy(
|
||||
isSelected = isSelected
|
||||
)
|
||||
is BlockView.DataView.EmptyData -> view.copy(
|
||||
isSelected = isSelected
|
||||
)
|
||||
is BlockView.DataView.EmptySource -> view.copy(
|
||||
isSelected = isSelected
|
||||
)
|
||||
else -> view.also { check(view !is BlockView.Permission) }
|
||||
}
|
||||
}
|
||||
|
@ -587,6 +596,9 @@ fun List<BlockView>.clearSearchHighlights(): List<BlockView> = map { view ->
|
|||
is BlockView.LinkToObject.Default.Card.MediumIconCover -> view.copy(searchFields = emptyList())
|
||||
is BlockView.LinkToObject.Archived -> view.copy(searchFields = emptyList())
|
||||
is BlockView.Table -> view.copy(cells = view.cells.map { cell -> cell.clearHighlight() })
|
||||
is BlockView.DataView.Default -> view.copy(searchFields = emptyList())
|
||||
is BlockView.DataView.EmptyData -> view.copy(searchFields = emptyList())
|
||||
is BlockView.DataView.EmptySource -> view.copy(searchFields = emptyList())
|
||||
else -> view.also { check(view !is BlockView.Searchable) }
|
||||
}
|
||||
}
|
||||
|
@ -687,6 +699,18 @@ fun List<BlockView>.highlight(
|
|||
val updatedCells = view.cells.map { it.addHighlight(highlighter) }
|
||||
view.copy(cells = updatedCells)
|
||||
}
|
||||
is BlockView.DataView.EmptySource -> {
|
||||
val fields = listOf(DEFAULT_SEARCH_FIELD_KEY to view.title.orEmpty())
|
||||
view.copy(searchFields = highlighter(fields))
|
||||
}
|
||||
is BlockView.DataView.EmptyData -> {
|
||||
val fields = listOf(DEFAULT_SEARCH_FIELD_KEY to view.title.orEmpty())
|
||||
view.copy(searchFields = highlighter(fields))
|
||||
}
|
||||
is BlockView.DataView.Default -> {
|
||||
val fields = listOf(DEFAULT_SEARCH_FIELD_KEY to view.title.orEmpty())
|
||||
view.copy(searchFields = highlighter(fields))
|
||||
}
|
||||
else -> {
|
||||
view.also { v ->
|
||||
if (v is BlockView.Searchable) {
|
||||
|
@ -742,6 +766,9 @@ fun BlockView.setHighlight(
|
|||
is BlockView.LinkToObject.Default.Card.SmallIconCover -> copy(searchFields = highlights)
|
||||
is BlockView.LinkToObject.Default.Card.MediumIconCover -> copy(searchFields = highlights)
|
||||
is BlockView.LinkToObject.Archived -> copy(searchFields = highlights)
|
||||
is BlockView.DataView.EmptySource -> copy(searchFields = highlights)
|
||||
is BlockView.DataView.EmptyData -> copy(searchFields = highlights)
|
||||
is BlockView.DataView.Default -> copy(searchFields = highlights)
|
||||
else -> this.also { check(this !is BlockView.Searchable) }
|
||||
}
|
||||
|
||||
|
@ -1034,6 +1061,9 @@ fun BlockView.updateSelection(newSelection: Boolean) = when (this) {
|
|||
is BlockView.Latex -> copy(isSelected = newSelection)
|
||||
is BlockView.TableOfContents -> copy(isSelected = newSelection)
|
||||
is BlockView.Table -> copy(isSelected = newSelection)
|
||||
is BlockView.DataView.EmptyData -> copy(isSelected = newSelection)
|
||||
is BlockView.DataView.EmptySource -> copy(isSelected = newSelection)
|
||||
is BlockView.DataView.Default -> copy(isSelected = newSelection)
|
||||
else -> this.also {
|
||||
if (this is BlockView.Selectable)
|
||||
Timber.e("Error when change selection for Selectable BlockView $this")
|
||||
|
|
|
@ -78,4 +78,6 @@ sealed interface ListenerType {
|
|||
data class TableOfContents(val target: Id) : ListenerType
|
||||
data class TableEmptyCell(val cell: BlockView.Table.Cell) : ListenerType
|
||||
data class TableTextCell(val cell: BlockView.Table.Cell) : ListenerType
|
||||
|
||||
data class DataViewClick(val target: Id) : ListenerType
|
||||
}
|
|
@ -16,6 +16,9 @@ import com.anytypeio.anytype.presentation.editor.editor.model.types.Types.HOLDER
|
|||
import com.anytypeio.anytype.presentation.editor.editor.model.types.Types.HOLDER_CALLOUT
|
||||
import com.anytypeio.anytype.presentation.editor.editor.model.types.Types.HOLDER_CHECKBOX
|
||||
import com.anytypeio.anytype.presentation.editor.editor.model.types.Types.HOLDER_CODE_SNIPPET
|
||||
import com.anytypeio.anytype.presentation.editor.editor.model.types.Types.HOLDER_DATA_VIEW_DEFAULT
|
||||
import com.anytypeio.anytype.presentation.editor.editor.model.types.Types.HOLDER_DATA_VIEW_EMPTY_DATA
|
||||
import com.anytypeio.anytype.presentation.editor.editor.model.types.Types.HOLDER_DATA_VIEW_EMPTY_SOURCE
|
||||
import com.anytypeio.anytype.presentation.editor.editor.model.types.Types.HOLDER_DESCRIPTION
|
||||
import com.anytypeio.anytype.presentation.editor.editor.model.types.Types.HOLDER_DIVIDER_DOTS
|
||||
import com.anytypeio.anytype.presentation.editor.editor.model.types.Types.HOLDER_DIVIDER_LINE
|
||||
|
@ -1379,4 +1382,56 @@ sealed class BlockView : ViewType {
|
|||
|
||||
enum class Tab { CELL, COLUMN, ROW }
|
||||
}
|
||||
|
||||
sealed class DataView : BlockView(), Selectable, Decoratable, Searchable {
|
||||
|
||||
abstract val title: String?
|
||||
abstract val icon: ObjectIcon
|
||||
abstract val background: ThemeColor
|
||||
|
||||
/**
|
||||
* UI-model for a data view block. There is no master set.
|
||||
*/
|
||||
data class EmptySource(
|
||||
override val id: String,
|
||||
override val isSelected: Boolean,
|
||||
override val decorations: List<Decoration>,
|
||||
override val searchFields: List<Searchable.Field> = emptyList(),
|
||||
override val title: String?,
|
||||
override val icon: ObjectIcon,
|
||||
override val background: ThemeColor
|
||||
) : DataView() {
|
||||
override fun getViewType(): Int = HOLDER_DATA_VIEW_EMPTY_SOURCE
|
||||
}
|
||||
|
||||
/**
|
||||
* UI-model for a data view block. There is a master set but no source for the set
|
||||
*/
|
||||
data class EmptyData(
|
||||
override val id: String,
|
||||
override val isSelected: Boolean,
|
||||
override val decorations: List<Decoration>,
|
||||
override val searchFields: List<Searchable.Field> = emptyList(),
|
||||
override val title: String?,
|
||||
override val icon: ObjectIcon,
|
||||
override val background: ThemeColor
|
||||
) : DataView() {
|
||||
override fun getViewType(): Int = HOLDER_DATA_VIEW_EMPTY_DATA
|
||||
}
|
||||
|
||||
/**
|
||||
* UI-model for a data view block. There is a master set and source for the set
|
||||
*/
|
||||
data class Default(
|
||||
override val id: String,
|
||||
override val isSelected: Boolean,
|
||||
override val decorations: List<Decoration>,
|
||||
override val searchFields: List<Searchable.Field> = emptyList(),
|
||||
override val title: String?,
|
||||
override val icon: ObjectIcon,
|
||||
override val background: ThemeColor
|
||||
) : DataView() {
|
||||
override fun getViewType(): Int = HOLDER_DATA_VIEW_DEFAULT
|
||||
}
|
||||
}
|
||||
}
|
|
@ -70,4 +70,8 @@ object Types {
|
|||
const val HOLDER_TOC = 54
|
||||
const val HOLDER_CALLOUT = 55
|
||||
const val HOLDER_TABLE = 56
|
||||
|
||||
const val HOLDER_DATA_VIEW_DEFAULT = 300
|
||||
const val HOLDER_DATA_VIEW_EMPTY_SOURCE = 301
|
||||
const val HOLDER_DATA_VIEW_EMPTY_DATA = 302
|
||||
}
|
|
@ -777,6 +777,20 @@ class DefaultBlockViewRenderer @Inject constructor(
|
|||
)
|
||||
)
|
||||
}
|
||||
is Content.DataView -> {
|
||||
isPreviousBlockMedia = false
|
||||
mCounter = 0
|
||||
result.add(
|
||||
dataView(
|
||||
mode = mode,
|
||||
block = block,
|
||||
content = content,
|
||||
details = details,
|
||||
selection = selection,
|
||||
schema = parentScheme
|
||||
)
|
||||
)
|
||||
}
|
||||
else -> {}
|
||||
}
|
||||
}
|
||||
|
@ -2145,4 +2159,67 @@ class DefaultBlockViewRenderer @Inject constructor(
|
|||
is Cursor.Range -> cursor.range.first
|
||||
}
|
||||
}
|
||||
|
||||
private fun dataView(
|
||||
mode: EditorMode,
|
||||
block: Block,
|
||||
content: Content.DataView,
|
||||
details: Block.Details,
|
||||
selection: Set<Id>,
|
||||
schema: NestedDecorationData
|
||||
): BlockView.DataView {
|
||||
val targetObjectId = content.targetObjectId
|
||||
val isSelected = checkIfSelected(
|
||||
mode = mode,
|
||||
block = block,
|
||||
selection = selection
|
||||
)
|
||||
val background = block.parseThemeBackgroundColor()
|
||||
val decorations = buildNestedDecorationData(
|
||||
block = block,
|
||||
parentScheme = schema,
|
||||
currentDecoration = DecorationData(
|
||||
style = DecorationData.Style.Card,
|
||||
background = background
|
||||
)
|
||||
).toBlockViewDecoration(block)
|
||||
if (targetObjectId.isBlank()) {
|
||||
return BlockView.DataView.EmptySource(
|
||||
id = block.id,
|
||||
decorations = decorations,
|
||||
isSelected = isSelected,
|
||||
background = background,
|
||||
icon = ObjectIcon.None,
|
||||
title = null
|
||||
)
|
||||
} else {
|
||||
val targetSet = ObjectWrapper.Basic(
|
||||
map = details.details[content.targetObjectId]?.map ?: emptyMap()
|
||||
)
|
||||
val icon = ObjectIcon.getEditorLinkToObjectIcon(
|
||||
obj = targetSet,
|
||||
layout = targetSet.layout,
|
||||
builder = urlBuilder
|
||||
)
|
||||
if (targetSet.setOf.isEmpty()) {
|
||||
return BlockView.DataView.EmptyData(
|
||||
id = block.id,
|
||||
decorations = decorations,
|
||||
isSelected = isSelected,
|
||||
title = targetSet.name,
|
||||
background = background,
|
||||
icon = icon
|
||||
)
|
||||
} else {
|
||||
return BlockView.DataView.Default(
|
||||
id = block.id,
|
||||
decorations = decorations,
|
||||
isSelected = isSelected,
|
||||
title = targetSet.name,
|
||||
background = background,
|
||||
icon = icon
|
||||
)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
|
@ -348,6 +348,9 @@ fun List<BlockView>.toggleTableMode(
|
|||
is BlockView.Unsupported -> view.copy(isSelected = false)
|
||||
is BlockView.Upload.Bookmark -> view.copy(isSelected = false)
|
||||
is BlockView.Relation.Deleted -> view.copy(isSelected = false)
|
||||
is BlockView.DataView.Default -> view.copy(isSelected = false)
|
||||
is BlockView.DataView.EmptyData -> view.copy(isSelected = false)
|
||||
is BlockView.DataView.EmptySource -> view.copy(isSelected = false)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -473,7 +473,8 @@ class ObjectSetReducerTest {
|
|||
filters = listOf()
|
||||
)
|
||||
),
|
||||
relations = listOf()
|
||||
relations = listOf(),
|
||||
targetObjectId = (dataView.content as Block.Content.DataView).targetObjectId
|
||||
),
|
||||
fields = Block.Fields.empty(),
|
||||
children = listOf()
|
||||
|
@ -573,7 +574,8 @@ class ObjectSetReducerTest {
|
|||
filters = expectedFilters
|
||||
)
|
||||
),
|
||||
relations = listOf()
|
||||
relations = listOf(),
|
||||
targetObjectId = (dataView.content as Block.Content.DataView).targetObjectId
|
||||
),
|
||||
fields = Block.Fields.empty(),
|
||||
children = listOf()
|
||||
|
@ -673,7 +675,8 @@ class ObjectSetReducerTest {
|
|||
filters = viewer1.filters
|
||||
)
|
||||
),
|
||||
relations = listOf()
|
||||
relations = listOf(),
|
||||
targetObjectId = (dataView.content as Block.Content.DataView).targetObjectId
|
||||
),
|
||||
fields = Block.Fields.empty(),
|
||||
children = listOf()
|
||||
|
|
|
@ -6,14 +6,16 @@ fun StubDataView(
|
|||
id : Id = MockDataFactory.randomUuid(),
|
||||
views: List<DVViewer> = emptyList(),
|
||||
relations: List<RelationLink> = emptyList(),
|
||||
sources: List<Id> = emptyList()
|
||||
sources: List<Id> = emptyList(),
|
||||
targetObjectId: Id = MockDataFactory.randomUuid()
|
||||
) : Block = Block(
|
||||
id = id,
|
||||
content = DV(
|
||||
sources = sources,
|
||||
relations = emptyList(),
|
||||
relationsIndex= relations,
|
||||
viewers = views
|
||||
viewers = views,
|
||||
targetObjectId = targetObjectId
|
||||
),
|
||||
children = emptyList(),
|
||||
fields = Block.Fields.empty()
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue