diff --git a/core-ui/src/main/java/com/anytypeio/anytype/core_ui/features/editor/holders/other/TableOfContents.kt b/core-ui/src/main/java/com/anytypeio/anytype/core_ui/features/editor/holders/other/TableOfContents.kt index d0546765db..d1ab2f1d88 100644 --- a/core-ui/src/main/java/com/anytypeio/anytype/core_ui/features/editor/holders/other/TableOfContents.kt +++ b/core-ui/src/main/java/com/anytypeio/anytype/core_ui/features/editor/holders/other/TableOfContents.kt @@ -33,10 +33,6 @@ class TableOfContents( fallback = { e -> itemView.onTouchEvent(e) } ) - init { - itemView.setOnTouchListener { v, e -> editorTouchProcessor.process(v, e) } - } - fun bind(item: BlockView.TableOfContents, clicked: (ListenerType) -> Unit) { cleanup() selected.isSelected = item.isSelected @@ -45,6 +41,7 @@ class TableOfContents( id = generateViewId() setPadding(getPadding(header.depth), 0, 0, 0) setName(header.name) + setOnTouchListener { v, e -> editorTouchProcessor.process(v, e) } setOnClickListener { clicked.invoke( ListenerType.TableOfContentsItem( @@ -53,10 +50,6 @@ class TableOfContents( ) ) } - setOnLongClickListener { - clicked.invoke(ListenerType.LongClick(item.id)) - true - } } container.addView(textview) } diff --git a/core-ui/src/main/java/com/anytypeio/anytype/core_ui/widgets/text/TableOfContentsItemWidget.kt b/core-ui/src/main/java/com/anytypeio/anytype/core_ui/widgets/text/TableOfContentsItemWidget.kt index 87abebae46..e87a2b7c30 100644 --- a/core-ui/src/main/java/com/anytypeio/anytype/core_ui/widgets/text/TableOfContentsItemWidget.kt +++ b/core-ui/src/main/java/com/anytypeio/anytype/core_ui/widgets/text/TableOfContentsItemWidget.kt @@ -5,6 +5,7 @@ import android.graphics.Paint import android.util.AttributeSet import android.view.LayoutInflater import android.widget.FrameLayout +import com.anytypeio.anytype.core_ui.R import com.anytypeio.anytype.core_ui.databinding.TvTableOfContentsBinding class TableOfContentsItemWidget @JvmOverloads constructor( @@ -23,6 +24,6 @@ class TableOfContentsItemWidget @JvmOverloads constructor( } fun setName(name: String) { - textView.text = name + textView.text = name.ifBlank { resources.getString(R.string.untitled) } } } \ No newline at end of file diff --git a/presentation/src/main/java/com/anytypeio/anytype/presentation/editor/render/DefaultBlockViewRenderer.kt b/presentation/src/main/java/com/anytypeio/anytype/presentation/editor/render/DefaultBlockViewRenderer.kt index de0e95feaa..e9250438d2 100644 --- a/presentation/src/main/java/com/anytypeio/anytype/presentation/editor/render/DefaultBlockViewRenderer.kt +++ b/presentation/src/main/java/com/anytypeio/anytype/presentation/editor/render/DefaultBlockViewRenderer.kt @@ -543,7 +543,6 @@ class DefaultBlockViewRenderer @Inject constructor( result.add( toc( block = block, - indent = indent, mode = mode, selection = selection, blocks = children @@ -1455,17 +1454,30 @@ class DefaultBlockViewRenderer @Inject constructor( private fun toc( block: Block, blocks: List, - indent: Int, mode: EditorMode, selection: Set ): BlockView.TableOfContents { val headers = blocks.filter { (it.content as? Content.Text)?.isHeader() ?: false } - var depth = 0 + var isH1Present = false + var isH2Present = false val items = mutableListOf() headers.forEachIndexed { index, b -> val content = b.content() - if (content.style == Content.Text.Style.H1) { - depth = 0 + var depth = 0 + when (content.style) { + Content.Text.Style.H1 -> { + isH1Present = true + isH2Present = false + } + Content.Text.Style.H2 -> { + isH2Present = true + if (isH1Present) depth += 1 + } + Content.Text.Style.H3 -> { + if (isH1Present) depth += 1 + if (isH2Present) depth += 1 + } + else -> {} } val item = BlockView.TableOfContentsItem( id = b.id, @@ -1473,24 +1485,6 @@ class DefaultBlockViewRenderer @Inject constructor( depth = depth ) items.add(item) - val next = if (index + 1 < headers.size) { - headers[index + 1] - } else { - null - } - if (next != null) { - val contentNext = next.content() - if (content.style == Content.Text.Style.H1 && ( - contentNext.style == Content.Text.Style.H2 - || contentNext.style == Content.Text.Style.H3 - ) - ) { - depth += 1 - } - if (content.style == Content.Text.Style.H2 && contentNext.style == Content.Text.Style.H3) { - depth += 1 - } - } } val toc = BlockView.TableOfContents( diff --git a/presentation/src/test/java/com/anytypeio/anytype/presentation/editor/editor/EditorTableOfContentsBlockTest.kt b/presentation/src/test/java/com/anytypeio/anytype/presentation/editor/editor/EditorTableOfContentsBlockTest.kt index d0d38c3de9..19c2c7b122 100644 --- a/presentation/src/test/java/com/anytypeio/anytype/presentation/editor/editor/EditorTableOfContentsBlockTest.kt +++ b/presentation/src/test/java/com/anytypeio/anytype/presentation/editor/editor/EditorTableOfContentsBlockTest.kt @@ -597,4 +597,183 @@ class EditorTableOfContentsBlockTest : EditorPresentationTestSetup() { assertEquals(expected, result) } + + @Test + fun `should have proper depth for headers`() { + val title = MockTypicalDocumentFactory.title + val header = MockTypicalDocumentFactory.header + + val blockHeaderOne1 = Block( + id = MockDataFactory.randomUuid(), + fields = Block.Fields(emptyMap()), + content = Block.Content.Text( + text = MockDataFactory.randomString(), + marks = emptyList(), + style = Block.Content.Text.Style.H1 + ), + children = emptyList() + ) + + val blockHeaderTwo1 = Block( + id = MockDataFactory.randomUuid(), + fields = Block.Fields(emptyMap()), + content = Block.Content.Text( + text = "", + marks = emptyList(), + style = Block.Content.Text.Style.H2 + ), + children = emptyList() + ) + + val blockHeaderTwo2 = Block( + id = MockDataFactory.randomUuid(), + fields = Block.Fields(emptyMap()), + content = Block.Content.Text( + text = "", + marks = emptyList(), + style = Block.Content.Text.Style.H2 + ), + children = emptyList() + ) + + val blockHeaderThree = Block( + id = MockDataFactory.randomUuid(), + fields = Block.Fields(emptyMap()), + content = Block.Content.Text( + text = "", + marks = emptyList(), + style = Block.Content.Text.Style.H3 + ), + children = emptyList() + ) + + val blockHeaderThree2 = Block( + id = MockDataFactory.randomUuid(), + fields = Block.Fields(emptyMap()), + content = Block.Content.Text( + text = "", + marks = emptyList(), + style = Block.Content.Text.Style.H3 + ), + children = emptyList() + ) + + val blockToC = Block( + id = MockDataFactory.randomUuid(), + fields = Block.Fields(emptyMap()), + content = Block.Content.TableOfContents, + children = emptyList() + ) + + val page = Block( + id = root, + fields = Block.Fields(emptyMap()), + content = Block.Content.Smart(SmartBlockType.PAGE), + children = listOf( + header.id, + blockToC.id, + blockHeaderOne1.id, + blockHeaderTwo1.id, + blockHeaderThree.id, + blockHeaderTwo2.id, + blockHeaderThree2.id + ) + ) + + val doc = listOf( + page, header, title, + blockToC, + blockHeaderOne1, + blockHeaderTwo1, + blockHeaderThree, + blockHeaderTwo2, + blockHeaderThree2 + ) + + stubInterceptEvents() + stubInterceptThreadStatus() + stubGetObjectTypes(objectTypes = listOf()) + stubOpenDocument( + document = doc, + details = Block.Details(), + relations = listOf() + ) + stubUpdateText() + + val vm = buildViewModel() + + //TESTING + vm.apply { onStart(root) } + + val expected = ViewState.Success( + blocks = listOf( + BlockView.Title.Basic( + id = title.id, + isFocused = false, + text = title.content().text, + mode = BlockView.Mode.EDIT + ), + BlockView.TableOfContents( + id = blockToC.id, + backgroundColor = blockToC.backgroundColor, + isSelected = false, + items = listOf( + BlockView.TableOfContentsItem( + id = blockHeaderOne1.id, + name = blockHeaderOne1.content.asText().text, + depth = 0 + ), + BlockView.TableOfContentsItem( + id = blockHeaderTwo1.id, + name = blockHeaderTwo1.content.asText().text, + depth = 1 + ), + BlockView.TableOfContentsItem( + id = blockHeaderThree.id, + name = blockHeaderThree.content.asText().text, + depth = 2 + ), + BlockView.TableOfContentsItem( + id = blockHeaderTwo2.id, + name = blockHeaderTwo2.content.asText().text, + depth = 1 + ), + BlockView.TableOfContentsItem( + id = blockHeaderThree2.id, + name = blockHeaderThree2.content.asText().text, + depth = 2 + ) + ) + ), + BlockView.Text.Header.One( + id = blockHeaderOne1.id, + indent = 0, + text = blockHeaderOne1.content.asText().text + ), + BlockView.Text.Header.Two( + id = blockHeaderTwo1.id, + indent = 0, + text = blockHeaderTwo1.content.asText().text + ), + BlockView.Text.Header.Three( + id = blockHeaderThree.id, + indent = 0, + text = blockHeaderThree.content.asText().text + ), + BlockView.Text.Header.Two( + id = blockHeaderTwo2.id, + indent = 0, + text = blockHeaderTwo2.content.asText().text + ), + BlockView.Text.Header.Three( + id = blockHeaderThree2.id, + indent = 0, + text = blockHeaderThree2.content.asText().text + ) + ) + ) + val result = vm.state.test().value() + + assertEquals(expected, result) + } } \ No newline at end of file