1
0
Fork 0
mirror of https://github.com/anyproto/anytype-kotlin.git synced 2025-06-08 05:47:05 +09:00

Editor | Feature | Code block, design and clicks (#2231)

* code block update

* code block, holder design

* block list extension + tests

* only background style menu for text blocks

* code block fixes

* update gradle

* rename fun

* back android 7 fix

Co-authored-by: konstantiniiv <ki@anytype.io>
This commit is contained in:
Konstantin Ivanov 2022-05-05 09:25:52 +03:00 committed by GitHub
parent 1eeb6a0067
commit 9eeea1e722
Signed by: github
GPG key ID: 4AEE18F83AFDEB23
7 changed files with 176 additions and 64 deletions

View file

@ -22,7 +22,7 @@ buildscript {
mavenCentral()
}
dependencies {
classpath 'com.android.tools.build:gradle:7.1.1'
classpath 'com.android.tools.build:gradle:7.1.3'
classpath "org.jetbrains.kotlin:kotlin-gradle-plugin:$kotlin_version"
classpath "androidx.navigation:navigation-safe-args-gradle-plugin:$nav_version"
classpath 'com.google.gms:google-services:4.3.10'

View file

@ -271,4 +271,9 @@ fun Document.updateTextContent(
fun List<Block>.getChildrenIdsList(parent: Id): List<String> {
val root = this.firstOrNull { it.id == parent }
return root?.children ?: emptyList()
}
}
fun List<Block>.isAllTextAndNoneCodeBlocks(): Boolean =
all { block ->
block.content is Content.Text && block.content.style != Content.Text.Style.CODE_SNIPPET
}

View file

@ -1,16 +1,15 @@
package com.anytypeio.anytype.core_ui.features.editor.holders.other
import android.graphics.drawable.GradientDrawable
import android.graphics.drawable.ColorDrawable
import android.os.Build
import android.os.Build.VERSION_CODES.N
import android.os.Build.VERSION_CODES.N_MR1
import android.text.Editable
import android.view.View
import android.view.inputmethod.InputMethodManager
import android.widget.FrameLayout
import android.widget.LinearLayout
import android.widget.TextView
import androidx.core.view.updateLayoutParams
import androidx.recyclerview.widget.RecyclerView
import com.anytypeio.anytype.core_ui.R
import com.anytypeio.anytype.core_ui.databinding.ItemBlockCodeSnippetBinding
import com.anytypeio.anytype.core_ui.extensions.lighter
@ -38,15 +37,13 @@ class Code(val binding: ItemBlockCodeSnippetBinding) : BlockViewHolder(binding.r
get() = itemView
val content: CodeTextInputWidget
get() = binding.snippet
val container: LinearLayout
get() = binding.snippetContainer
val editorTouchProcessor = EditorTouchProcessor(
fallback = { e -> itemView.onTouchEvent(e) }
)
init {
itemView.setOnTouchListener { v, e -> editorTouchProcessor.process(v, e) }
content.setOnTouchListener { v, e -> editorTouchProcessor.process(v, e) }
}
fun bind(
@ -97,7 +94,7 @@ class Code(val binding: ItemBlockCodeSnippetBinding) : BlockViewHolder(binding.r
content.selectionWatcher = { onSelectionChanged(item.id, it) }
}
itemView.setOnClickListener {
content.setOnClickListener {
onTextInputClicked(item.id)
if (Build.VERSION.SDK_INT == N || Build.VERSION.SDK_INT == N_MR1) {
content.context.imm().showSoftInput(content, InputMethodManager.SHOW_FORCED)
@ -118,11 +115,8 @@ class Code(val binding: ItemBlockCodeSnippetBinding) : BlockViewHolder(binding.r
}
fun indentize(item: BlockView.Indentable) {
binding.snippetContainer.updateLayoutParams<FrameLayout.LayoutParams> {
apply {
val extra = item.indent * dimen(R.dimen.indent)
leftMargin = 0 + extra
}
root.updateLayoutParams<RecyclerView.LayoutParams> {
leftMargin = item.indent * dimen(R.dimen.indent)
}
}
@ -174,7 +168,7 @@ class Code(val binding: ItemBlockCodeSnippetBinding) : BlockViewHolder(binding.r
}
fun select(item: BlockView.Selectable) {
root.isSelected = item.isSelected
binding.selected.isSelected = item.isSelected
}
fun setFocus(item: Focusable) {
@ -206,11 +200,11 @@ class Code(val binding: ItemBlockCodeSnippetBinding) : BlockViewHolder(binding.r
Timber.d("Setting background color: $color")
val value = ThemeColor.values().find { value -> value.title == color }
if (value != null && value != ThemeColor.DEFAULT) {
(container.background as? GradientDrawable)?.setColor(root.resources.lighter(value, 0))
(root.background as? ColorDrawable)?.color = root.resources.lighter(value, 0)
} else {
val defaultBackgroundColor =
content.context.resources.getColor(R.color.shape_tertiary, null)
(container.background as? GradientDrawable)?.setColor(defaultBackgroundColor)
(root.background as? ColorDrawable)?.color = defaultBackgroundColor
}
}

View file

@ -1,58 +1,56 @@
<?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/DefaultCodeBlockRootStyle"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginStart="8dp"
android:layout_marginTop="1dp"
android:layout_marginEnd="8dp"
android:layout_marginBottom="1dp"
android:background="@drawable/item_block_code_multi_select_mode_selector"
android:paddingStart="12dp"
android:paddingTop="6dp"
android:paddingEnd="12dp"
android:paddingBottom="6dp">
android:background="@color/shape_tertiary">
<LinearLayout
android:id="@+id/snippetContainer"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginTop="1dp"
android:layout_marginBottom="1dp"
android:background="@drawable/item_block_code_multi_select_unselected"
android:orientation="vertical"
android:paddingStart="20dp"
android:paddingEnd="20dp">
android:orientation="vertical">
<TextView
android:id="@+id/code_menu"
style="@style/BlockCodeLanguageMenuStyle"
android:id="@+id/codeMenu"
style="@style/DefaultCodeBlockLanguageMenuStyle"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginTop="@dimen/dp_12"
android:layout_marginStart="20dp"
android:layout_marginTop="13dp"
android:text="@string/block_code_menu_title" />
<HorizontalScrollView
android:fillViewport="true"
android:scrollbars="none"
android:overScrollMode="never"
android:id="@+id/scroll"
android:layout_width="match_parent"
android:layout_height="wrap_content">
android:layout_height="wrap_content"
android:fillViewport="true"
android:overScrollMode="never"
android:scrollbars="none">
<com.anytypeio.anytype.core_ui.widgets.text.CodeTextInputWidget
android:id="@+id/snippet"
style="@style/BlockCodeContentStyle"
style="@style/DefaultCodeBlockContentStyle"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:fontFamily="monospace"
android:paddingTop="23dp"
android:paddingBottom="30dp"
android:layout_marginStart="20dp"
android:focusable="true"
android:paddingTop="18dp"
android:paddingEnd="32dp"
android:paddingBottom="21dp"
android:textIsSelectable="true"
tools:text="@string/default_text_placeholder" />
</HorizontalScrollView>
</HorizontalScrollView>
</LinearLayout>
<View
android:id="@+id/selected"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:layout_marginStart="@dimen/dp_8"
android:layout_marginEnd="@dimen/dp_8"
android:background="@drawable/item_block_multi_select_mode_selector"
tools:background="@drawable/item_block_multi_select_selected" />
</FrameLayout>

View file

@ -148,23 +148,6 @@
<item name="android:paddingBottom">4dp</item>
</style>
<style name="BlockCodeContentStyle">
<item name="android:inputType">textMultiLine|textNoSuggestions</item>
<item name="android:background">@null</item>
<item name="android:lineSpacingExtra">7sp</item>
<item name="android:textColor">@color/text_primary</item>
<item name="android:textSize">15sp</item>
</style>
<style name="BlockCodeLanguageMenuStyle">
<item name="android:fontFamily">@font/inter_regular</item>
<item name="android:lineSpacingExtra">7sp</item>
<item name="android:drawablePadding">4dp</item>
<item name="android:drawableEnd">@drawable/ic_turn_into_arrow</item>
<item name="android:textColor">@color/text_secondary</item>
<item name="android:textSize">15sp</item>
</style>
<style name="BlockBookmarkTitleStyle">
<item name="android:fontFamily">@font/inter_medium</item>
<item name="android:textSize">13sp</item>
@ -1013,4 +996,28 @@
<item name="android:textSize">15sp</item>
</style>
<!-- Editor, Code block -->
<style name="DefaultCodeBlockRootStyle">
<item name="android:layout_marginTop">@dimen/dp_10</item>
<item name="android:layout_marginBottom">@dimen/dp_10</item>
</style>
<style name="DefaultCodeBlockContentStyle">
<item name="android:inputType">textMultiLine|textNoSuggestions</item>
<item name="android:background">@null</item>
<item name="android:lineSpacingExtra">7sp</item>
<item name="android:textColor">@color/text_primary</item>
<item name="android:textSize">15sp</item>
<item name="android:fontFamily">monospace</item>
</style>
<style name="DefaultCodeBlockLanguageMenuStyle">
<item name="android:fontFamily">@font/inter_regular</item>
<item name="android:lineSpacingExtra">7sp</item>
<item name="android:drawablePadding">4dp</item>
<item name="android:drawableEnd">@drawable/ic_turn_into_arrow</item>
<item name="android:textColor">@color/text_secondary</item>
<item name="android:textSize">15sp</item>
</style>
</resources>

View file

@ -5,7 +5,9 @@ import com.anytypeio.anytype.domain.common.MockDataFactory
import com.anytypeio.anytype.core_models.ext.*
import org.junit.Test
import kotlin.test.assertEquals
import kotlin.test.assertFalse
import kotlin.test.assertNull
import kotlin.test.assertTrue
class BlockExtensionTest {
@ -1015,4 +1017,109 @@ class BlockExtensionTest {
assertNull(result)
}
@Test
fun `should return true on all non code and texted blocks`() {
val root = MockDataFactory.randomUuid()
val a = Block(
id = MockDataFactory.randomUuid(),
fields = Block.Fields.empty(),
children = emptyList(),
content = Block.Content.Text(
text = MockDataFactory.randomString(),
marks = emptyList(),
style = Block.Content.Text.Style.NUMBERED
)
)
val b = Block(
id = MockDataFactory.randomUuid(),
fields = Block.Fields.empty(),
children = emptyList(),
content = Block.Content.Text(
text = MockDataFactory.randomString(),
marks = emptyList(),
style = (Block.Content.Text.Style.P)
)
)
val document = listOf(a, b)
val result = document.isAllTextAndNoneCodeBlocks()
assertTrue(result)
}
@Test
fun `should return false on texted blocks and code block`() {
val root = MockDataFactory.randomUuid()
val a = Block(
id = MockDataFactory.randomUuid(),
fields = Block.Fields.empty(),
children = emptyList(),
content = Block.Content.Text(
text = MockDataFactory.randomString(),
marks = emptyList(),
style = Block.Content.Text.Style.NUMBERED
)
)
val b = Block(
id = MockDataFactory.randomUuid(),
fields = Block.Fields.empty(),
children = emptyList(),
content = Block.Content.Text(
text = MockDataFactory.randomString(),
marks = emptyList(),
style = (Block.Content.Text.Style.P)
)
)
val c = Block(
id = MockDataFactory.randomUuid(),
fields = Block.Fields.empty(),
children = emptyList(),
content = Block.Content.Text(
text = MockDataFactory.randomString(),
marks = emptyList(),
style = (Block.Content.Text.Style.CODE_SNIPPET)
)
)
val document = listOf(a, b, c)
val result = document.isAllTextAndNoneCodeBlocks()
assertFalse(result)
}
@Test
fun `should return false on media blocks`() {
val root = MockDataFactory.randomUuid()
val a = Block(
id = MockDataFactory.randomUuid(),
fields = Block.Fields.empty(),
children = emptyList(),
content = Block.Content.File()
)
val b = Block(
id = MockDataFactory.randomUuid(),
fields = Block.Fields.empty(),
children = emptyList(),
content = Block.Content.File()
)
val document = listOf(a, b)
val result = document.isAllTextAndNoneCodeBlocks()
assertFalse(result)
}
}

View file

@ -29,6 +29,7 @@ import com.anytypeio.anytype.core_models.ext.asMap
import com.anytypeio.anytype.core_models.ext.content
import com.anytypeio.anytype.core_models.ext.descendants
import com.anytypeio.anytype.core_models.ext.getFirstLinkOrObjectMarkupParam
import com.anytypeio.anytype.core_models.ext.isAllTextAndNoneCodeBlocks
import com.anytypeio.anytype.core_models.ext.parents
import com.anytypeio.anytype.core_models.ext.process
import com.anytypeio.anytype.core_models.ext.sortByType
@ -2339,7 +2340,7 @@ class EditorViewModel(
private fun proceedWithMultiStyleToolbarEvent() {
val selected = blocks.filter { currentSelection().contains(it.id) }
val isAllSelectedText = selected.all { it.content is Content.Text }
val isAllSelectedText = selected.isAllTextAndNoneCodeBlocks()
mode = EditorMode.Styling.Multi(currentSelection())
if (isAllSelectedText) {
controlPanelInteractor.onEvent(