From 7cf46865b229e6f16849418fb0e64b6861c23a4c Mon Sep 17 00:00:00 2001 From: Mikhail Date: Mon, 3 Oct 2022 20:45:50 +0300 Subject: [PATCH] DROID-50 Editor | Tech | Create text watchers in oncreate (#2620) --- .../anytype/ui/editor/DragAndDropDelegate.kt | 2 +- .../core_ui/features/editor/BlockAdapter.kt | 236 +++--------- .../features/editor/BlockViewHolder.kt | 31 ++ .../features/editor/ItemProviderAdapter.kt | 5 + .../features/editor/TextBlockHolder.kt | 105 ++---- .../features/editor/holders/text/Bulleted.kt | 33 +- .../features/editor/holders/text/Callout.kt | 36 +- .../features/editor/holders/text/Checkbox.kt | 57 +-- .../features/editor/holders/text/Header.kt | 38 +- .../features/editor/holders/text/HeaderOne.kt | 2 +- .../editor/holders/text/HeaderThree.kt | 2 +- .../features/editor/holders/text/HeaderTwo.kt | 2 +- .../features/editor/holders/text/Highlight.kt | 30 +- .../features/editor/holders/text/Numbered.kt | 44 +-- .../features/editor/holders/text/Paragraph.kt | 29 +- .../features/editor/holders/text/Text.kt | 108 +++--- .../features/editor/holders/text/Toggle.kt | 61 +--- .../anytype/core_ui/BlockAdapterTest.kt | 220 +++++------ .../anytype/core_ui/HeaderBlockTest.kt | 12 - .../editor/BlockAdapterCheckboxTest.kt | 63 ---- .../editor/BlockAdapterMovementMethodTest.kt | 40 -- .../editor/BlockAdapterReadWriteModeTest.kt | 343 +----------------- .../features/editor/BlockAdapterToggleTest.kt | 91 ----- .../uitests/BlockAdapterCheckboxTest.kt | 148 ++++++++ .../uitests/BlockAdapterReadWriteModeTest.kt | 246 +++++++++++++ .../core_ui/uitests/BlockAdapterShared.kt | 12 +- .../core_ui/uitests/BlockAdapterToggleTest.kt | 106 ++++++ .../utils/view_action/ExtractViewAction.kt | 31 ++ 28 files changed, 863 insertions(+), 1270 deletions(-) create mode 100644 core-ui/src/main/java/com/anytypeio/anytype/core_ui/features/editor/ItemProviderAdapter.kt delete mode 100644 core-ui/src/test/java/com/anytypeio/anytype/core_ui/features/editor/BlockAdapterToggleTest.kt create mode 100644 core-ui/src/test/java/com/anytypeio/anytype/core_ui/uitests/BlockAdapterCheckboxTest.kt create mode 100644 core-ui/src/test/java/com/anytypeio/anytype/core_ui/uitests/BlockAdapterReadWriteModeTest.kt create mode 100644 core-ui/src/test/java/com/anytypeio/anytype/core_ui/uitests/BlockAdapterToggleTest.kt create mode 100644 test/android-utils/src/main/java/com/anytypeio/anytype/test_utils/utils/view_action/ExtractViewAction.kt diff --git a/app/src/main/java/com/anytypeio/anytype/ui/editor/DragAndDropDelegate.kt b/app/src/main/java/com/anytypeio/anytype/ui/editor/DragAndDropDelegate.kt index 1cad424f4c..73848c687a 100644 --- a/app/src/main/java/com/anytypeio/anytype/ui/editor/DragAndDropDelegate.kt +++ b/app/src/main/java/com/anytypeio/anytype/ui/editor/DragAndDropDelegate.kt @@ -139,7 +139,7 @@ class DragAndDropDelegate { ) val shadow = when (vh) { - is Text -> TextInputDragShadow(vh.content.id, vh.itemView, event) + is Text<*> -> TextInputDragShadow(vh.content.id, vh.itemView, event) is Code -> TextInputDragShadow(vh.content.id, vh.itemView, event) else -> DefaultEditorDragShadow(vh.itemView, event) } diff --git a/core-ui/src/main/java/com/anytypeio/anytype/core_ui/features/editor/BlockAdapter.kt b/core-ui/src/main/java/com/anytypeio/anytype/core_ui/features/editor/BlockAdapter.kt index ffa9a9367a..e8cf5927b6 100644 --- a/core-ui/src/main/java/com/anytypeio/anytype/core_ui/features/editor/BlockAdapter.kt +++ b/core-ui/src/main/java/com/anytypeio/anytype/core_ui/features/editor/BlockAdapter.kt @@ -106,10 +106,10 @@ import com.anytypeio.anytype.core_ui.features.editor.holders.text.Numbered import com.anytypeio.anytype.core_ui.features.editor.holders.text.Paragraph import com.anytypeio.anytype.core_ui.features.editor.holders.text.Text import com.anytypeio.anytype.core_ui.features.editor.holders.text.Toggle +import com.anytypeio.anytype.core_ui.features.editor.holders.upload.BookmarkUpload import com.anytypeio.anytype.core_ui.features.editor.holders.upload.FileUpload import com.anytypeio.anytype.core_ui.features.editor.holders.upload.PictureUpload import com.anytypeio.anytype.core_ui.features.editor.holders.upload.VideoUpload -import com.anytypeio.anytype.core_ui.features.editor.holders.upload.BookmarkUpload import com.anytypeio.anytype.core_ui.features.table.holders.TableBlockHolder import com.anytypeio.anytype.core_ui.tools.ClipboardInterceptor import com.anytypeio.anytype.core_ui.tools.DefaultTextWatcher @@ -173,7 +173,6 @@ 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.editor.editor.slash.SlashEvent -import com.anytypeio.anytype.presentation.relations.DocumentRelationView import timber.log.Timber import java.util.* @@ -215,7 +214,9 @@ class BlockAdapter( private val onDragListener: View.OnDragListener, private val lifecycle: Lifecycle, private val dragAndDropSelector: DragAndDropSelector, -) : RecyclerView.Adapter(), DragAndDropSelector by dragAndDropSelector { +) : RecyclerView.Adapter(), + ItemProviderAdapter, + DragAndDropSelector by dragAndDropSelector { private var blocks: List = initialBlock val views: List get() = blocks @@ -417,8 +418,11 @@ class BlockAdapter( Checkbox( binding = ItemBlockCheckboxBinding.inflate( inflater, parent, false - ), clicked = onClickListener - ) + ), + clicked = onClickListener + ).apply { + setCheckboxClickListener(onCheckboxClicked) + } } HOLDER_BULLET -> { Bulleted( @@ -438,8 +442,11 @@ class BlockAdapter( Toggle( binding = ItemBlockToggleBinding.inflate( inflater, parent, false - ), clicked = onClickListener - ) + ), + clicked = onClickListener + ).apply { + setupToggle(onToggleClicked, onTogglePlaceholderClicked) + } } HOLDER_DESCRIPTION -> { Description( @@ -590,7 +597,7 @@ class BlockAdapter( } HOLDER_BOOKMARK_UPLOAD -> { BookmarkUpload( - ItemBlockBookmarkUploadingBinding.inflate(inflater, parent, false) + ItemBlockBookmarkUploadingBinding.inflate(inflater, parent, false) ) } HOLDER_PICTURE -> { @@ -710,7 +717,7 @@ class BlockAdapter( else -> throw IllegalStateException("Unexpected view type: $viewType") } - if (holder is Text) { + if (holder is Text<*>) { holder.content.setOnDragListener(onDragListener) holder.content.editorTouchProcessor.onLongClick = { val pos = holder.bindingAdapterPosition @@ -747,6 +754,23 @@ class BlockAdapter( onSelectionChanged(view.id, selection) } } + holder.setupViewHolder( + onTextChanged = { editable -> + holder.withBlock { item -> + item.apply { + text = editable.toString() + marks = editable.marks() + } + onTextBlockTextChanged(item) + } + }, + onEmptyBlockBackspaceClicked = onEmptyBlockBackspaceClicked, + onSplitLineEnterClicked = onSplitLineEnterClicked, + onNonEmptyBlockBackspaceClicked = onNonEmptyBlockBackspaceClicked, + onMentionEvent = onMentionEvent, + onSlashEvent = onSlashEvent, + onBackPressedCallback = onBackPressedCallback, + ) } else { if (holder !is SupportCustomTouchProcessor) { when (holder) { @@ -823,33 +847,21 @@ class BlockAdapter( holder.processChangePayload( payloads = payloads.typeOf(), item = blocks[position], - onTextChanged = onTextBlockTextChanged, - onSelectionChanged = onSelectionChanged, - clicked = onClickListener, - onMentionEvent = onMentionEvent, - onSlashEvent = onSlashEvent + clicked = onClickListener ) } is Bulleted -> { holder.processChangePayload( payloads = payloads.typeOf(), item = blocks[position], - onTextChanged = onTextBlockTextChanged, - onSelectionChanged = onSelectionChanged, - clicked = onClickListener, - onMentionEvent = onMentionEvent, - onSlashEvent = onSlashEvent + clicked = onClickListener ) } is Checkbox -> { holder.processChangePayload( payloads = payloads.typeOf(), item = blocks[position], - onTextChanged = onTextBlockTextChanged, - onSelectionChanged = onSelectionChanged, - clicked = onClickListener, - onMentionEvent = onMentionEvent, - onSlashEvent = onSlashEvent + clicked = onClickListener ) } is Title.Document -> { @@ -874,77 +886,49 @@ class BlockAdapter( holder.processChangePayload( payloads = payloads.typeOf(), item = blocks[position], - onTextChanged = onTextBlockTextChanged, - onSelectionChanged = onSelectionChanged, clicked = onClickListener, - onMentionEvent = onMentionEvent, - onSlashEvent = onSlashEvent ) } is HeaderOne -> { holder.processChangePayload( payloads = payloads.typeOf(), item = blocks[position], - onTextChanged = onTextBlockTextChanged, - onSelectionChanged = onSelectionChanged, - clicked = onClickListener, - onMentionEvent = onMentionEvent, - onSlashEvent = onSlashEvent + clicked = onClickListener ) } is HeaderTwo -> { holder.processChangePayload( payloads = payloads.typeOf(), item = blocks[position], - onTextChanged = onTextBlockTextChanged, - onSelectionChanged = onSelectionChanged, clicked = onClickListener, - onMentionEvent = onMentionEvent, - onSlashEvent = onSlashEvent ) } is HeaderThree -> { holder.processChangePayload( payloads = payloads.typeOf(), item = blocks[position], - onTextChanged = onTextBlockTextChanged, - onSelectionChanged = onSelectionChanged, clicked = onClickListener, - onMentionEvent = onMentionEvent, - onSlashEvent = onSlashEvent ) } is Toggle -> { holder.processChangePayload( payloads = payloads.typeOf(), item = blocks[position], - onTextChanged = onTextBlockTextChanged, - onSelectionChanged = onSelectionChanged, - clicked = onClickListener, - onMentionEvent = onMentionEvent, - onSlashEvent = onSlashEvent + clicked = onClickListener ) } is Highlight -> { holder.processChangePayload( payloads = payloads.typeOf(), item = blocks[position], - onTextChanged = onTextBlockTextChanged, - onSelectionChanged = onSelectionChanged, - clicked = onClickListener, - onMentionEvent = onMentionEvent, - onSlashEvent = onSlashEvent + clicked = onClickListener ) } is Callout -> { holder.processChangePayload( payloads = payloads.typeOf(), item = blocks[position], - onTextChanged = onTextBlockTextChanged, - onSelectionChanged = onSelectionChanged, - clicked = onClickListener, - onMentionEvent = onMentionEvent, - onSlashEvent = onSlashEvent + clicked = onClickListener ) } is File -> { @@ -1140,130 +1124,16 @@ class BlockAdapter( override fun onBindViewHolder(holder: BlockViewHolder, position: Int) { if (isInDragAndDropMode) trySetDesiredAppearanceForDraggedItem(holder, position) when (holder) { - is Paragraph -> { - holder.bind( - item = blocks[position] as BlockView.Text.Paragraph, - onTextBlockTextChanged = onTextBlockTextChanged, - onMentionEvent = onMentionEvent, - onSlashEvent = onSlashEvent, - onEmptyBlockBackspaceClicked = onEmptyBlockBackspaceClicked, - onSplitLineEnterClicked = onSplitLineEnterClicked, - onNonEmptyBlockBackspaceClicked = onNonEmptyBlockBackspaceClicked, - onBackPressedCallback = onBackPressedCallback - ) - } - is HeaderOne -> { - holder.bind( - block = blocks[position] as BlockView.Text.Header.One, - onTextBlockTextChanged = onTextBlockTextChanged, - onMentionEvent = onMentionEvent, - onSlashEvent = onSlashEvent, - onEmptyBlockBackspaceClicked = onEmptyBlockBackspaceClicked, - onSplitLineEnterClicked = onSplitLineEnterClicked, - onNonEmptyBlockBackspaceClicked = onNonEmptyBlockBackspaceClicked, - onBackPressedCallback = onBackPressedCallback - ) - } - is HeaderTwo -> { - holder.bind( - block = blocks[position] as BlockView.Text.Header.Two, - onTextBlockTextChanged = onTextBlockTextChanged, - onMentionEvent = onMentionEvent, - onSlashEvent = onSlashEvent, - onEmptyBlockBackspaceClicked = onEmptyBlockBackspaceClicked, - onSplitLineEnterClicked = onSplitLineEnterClicked, - onNonEmptyBlockBackspaceClicked = onNonEmptyBlockBackspaceClicked, - onBackPressedCallback = onBackPressedCallback - ) - } - is HeaderThree -> { - holder.bind( - block = blocks[position] as BlockView.Text.Header.Three, - onTextBlockTextChanged = onTextBlockTextChanged, - onMentionEvent = onMentionEvent, - onSlashEvent = onSlashEvent, - onEmptyBlockBackspaceClicked = onEmptyBlockBackspaceClicked, - onSplitLineEnterClicked = onSplitLineEnterClicked, - onNonEmptyBlockBackspaceClicked = onNonEmptyBlockBackspaceClicked, - onBackPressedCallback = onBackPressedCallback - ) - } - is Checkbox -> { - holder.bind( - item = blocks[position] as BlockView.Text.Checkbox, - onTextBlockTextChanged = onTextBlockTextChanged, - onCheckboxClicked = onCheckboxClicked, - onMentionEvent = onMentionEvent, - onSlashEvent = onSlashEvent, - onEmptyBlockBackspaceClicked = onEmptyBlockBackspaceClicked, - onSplitLineEnterClicked = onSplitLineEnterClicked, - onNonEmptyBlockBackspaceClicked = onNonEmptyBlockBackspaceClicked, - onBackPressedCallback = onBackPressedCallback - ) - } - is Bulleted -> { - holder.bind( - item = blocks[position] as BlockView.Text.Bulleted, - onTextBlockTextChanged = onTextBlockTextChanged, - onMentionEvent = onMentionEvent, - onSlashEvent = onSlashEvent, - onEmptyBlockBackspaceClicked = onEmptyBlockBackspaceClicked, - onSplitLineEnterClicked = onSplitLineEnterClicked, - onNonEmptyBlockBackspaceClicked = onNonEmptyBlockBackspaceClicked, - onBackPressedCallback = onBackPressedCallback - ) - } - is Numbered -> { - holder.bind( - item = blocks[position] as BlockView.Text.Numbered, - onTextBlockTextChanged = onTextBlockTextChanged, - onMentionEvent = onMentionEvent, - onSlashEvent = onSlashEvent, - onEmptyBlockBackspaceClicked = onEmptyBlockBackspaceClicked, - onSplitLineEnterClicked = onSplitLineEnterClicked, - onNonEmptyBlockBackspaceClicked = onNonEmptyBlockBackspaceClicked, - onBackPressedCallback = onBackPressedCallback - ) - } - is Toggle -> { - holder.bind( - item = blocks[position] as BlockView.Text.Toggle, - onTextBlockTextChanged = onTextBlockTextChanged, - onTogglePlaceholderClicked = onTogglePlaceholderClicked, - onToggleClicked = onToggleClicked, - onMentionEvent = onMentionEvent, - onSlashEvent = onSlashEvent, - onEmptyBlockBackspaceClicked = onEmptyBlockBackspaceClicked, - onSplitLineEnterClicked = onSplitLineEnterClicked, - onNonEmptyBlockBackspaceClicked = onNonEmptyBlockBackspaceClicked, - onBackPressedCallback = onBackPressedCallback - ) - } - is Highlight -> { - holder.bind( - item = blocks[position] as BlockView.Text.Highlight, - onTextBlockTextChanged = onTextBlockTextChanged, - clicked = onClickListener, - onMentionEvent = onMentionEvent, - onSlashEvent = onSlashEvent, - onEmptyBlockBackspaceClicked = onEmptyBlockBackspaceClicked, - onSplitLineEnterClicked = onSplitLineEnterClicked, - onNonEmptyBlockBackspaceClicked = onNonEmptyBlockBackspaceClicked, - onBackPressedCallback = onBackPressedCallback - ) - } - is Callout -> { - holder.bind( - item = blocks[position] as BlockView.Text.Callout, - onTextBlockTextChanged = onTextBlockTextChanged, - onMentionEvent = onMentionEvent, - onSlashEvent = onSlashEvent, - onEmptyBlockBackspaceClicked = onEmptyBlockBackspaceClicked, - onSplitLineEnterClicked = onSplitLineEnterClicked, - onNonEmptyBlockBackspaceClicked = onNonEmptyBlockBackspaceClicked, - onBackPressedCallback = onBackPressedCallback - ) - } + is Paragraph -> holder.bind(blocks[position] as BlockView.Text.Paragraph) + is HeaderOne -> holder.bind(blocks[position] as BlockView.Text.Header.One) + is HeaderTwo -> holder.bind(blocks[position] as BlockView.Text.Header.Two) + is HeaderThree -> holder.bind(blocks[position] as BlockView.Text.Header.Three) + is Checkbox -> holder.bind(blocks[position] as BlockView.Text.Checkbox ) + is Bulleted -> holder.bind(blocks[position] as BlockView.Text.Bulleted) + is Numbered -> holder.bind(blocks[position] as BlockView.Text.Numbered) + is Toggle -> holder.bind(item = blocks[position] as BlockView.Text.Toggle) + is Highlight -> holder.bind(blocks[position] as BlockView.Text.Highlight) + is Callout -> holder.bind(blocks[position] as BlockView.Text.Callout) is Title.Document -> { holder.apply { bind( @@ -1542,7 +1412,7 @@ class BlockAdapter( } } - if (holder is Text) { + if (holder is Text<*>) { val block = blocks[position] @@ -1592,4 +1462,8 @@ class BlockAdapter( holder.onDecorationsChanged(decorations = block.decorations) } } + + override fun provide(pos: Int): BlockView { + return blocks[pos] + } } \ No newline at end of file diff --git a/core-ui/src/main/java/com/anytypeio/anytype/core_ui/features/editor/BlockViewHolder.kt b/core-ui/src/main/java/com/anytypeio/anytype/core_ui/features/editor/BlockViewHolder.kt index cc3266edca..5e76a61c00 100644 --- a/core-ui/src/main/java/com/anytypeio/anytype/core_ui/features/editor/BlockViewHolder.kt +++ b/core-ui/src/main/java/com/anytypeio/anytype/core_ui/features/editor/BlockViewHolder.kt @@ -7,6 +7,7 @@ import com.anytypeio.anytype.core_utils.ext.PopupExtensions import com.anytypeio.anytype.presentation.editor.editor.BlockDimensions import com.anytypeio.anytype.presentation.editor.editor.listener.ListenerType import com.anytypeio.anytype.presentation.editor.editor.model.BlockView +import timber.log.Timber /** * Viewholder for rendering different type of blocks (i.e its UI-models). @@ -50,3 +51,33 @@ open class BlockViewHolder(view: View) : RecyclerView.ViewHolder(view) { clicked(ListenerType.LongClick(target, dimensions)) } } + +inline fun BlockViewHolder.withBlock(block: (R) -> Unit) { + val pos = bindingAdapterPosition + val adapter = bindingAdapter + if (pos != RecyclerView.NO_POSITION && adapter is ItemProviderAdapter<*>) { + val view = adapter.provide(pos) + if (view is R) { + block(view) + } else { + if (view != null) { + Timber.w("Unexpected type: ${view::class.simpleName}") + } + } + } +} + +inline fun BlockViewHolder.provide() : R? { + val pos = bindingAdapterPosition + val adapter = bindingAdapter + return if (pos != RecyclerView.NO_POSITION && adapter is ItemProviderAdapter<*>) { + val view = adapter.provide(pos) + if (view is R) { + view + } else { + null + } + } else { + null + } +} diff --git a/core-ui/src/main/java/com/anytypeio/anytype/core_ui/features/editor/ItemProviderAdapter.kt b/core-ui/src/main/java/com/anytypeio/anytype/core_ui/features/editor/ItemProviderAdapter.kt new file mode 100644 index 0000000000..ce1e265276 --- /dev/null +++ b/core-ui/src/main/java/com/anytypeio/anytype/core_ui/features/editor/ItemProviderAdapter.kt @@ -0,0 +1,5 @@ +package com.anytypeio.anytype.core_ui.features.editor + +interface ItemProviderAdapter { + fun provide(pos: Int): T +} diff --git a/core-ui/src/main/java/com/anytypeio/anytype/core_ui/features/editor/TextBlockHolder.kt b/core-ui/src/main/java/com/anytypeio/anytype/core_ui/features/editor/TextBlockHolder.kt index cfce3dd354..9cbe647026 100644 --- a/core-ui/src/main/java/com/anytypeio/anytype/core_ui/features/editor/TextBlockHolder.kt +++ b/core-ui/src/main/java/com/anytypeio/anytype/core_ui/features/editor/TextBlockHolder.kt @@ -2,7 +2,6 @@ package com.anytypeio.anytype.core_ui.features.editor import android.graphics.drawable.Drawable import android.os.Build -import android.text.Editable import android.text.Spannable import android.view.ActionMode import android.view.Menu @@ -26,7 +25,6 @@ import com.anytypeio.anytype.core_ui.features.editor.decoration.DecoratableViewH import com.anytypeio.anytype.core_ui.features.editor.decoration.EditorDecorationContainer import com.anytypeio.anytype.core_ui.features.editor.holders.`interface`.TextHolder import com.anytypeio.anytype.core_ui.tools.DefaultSpannableFactory -import com.anytypeio.anytype.core_ui.tools.DefaultTextWatcher import com.anytypeio.anytype.core_ui.tools.MentionTextWatcher import com.anytypeio.anytype.core_ui.tools.SlashTextWatcher import com.anytypeio.anytype.core_ui.tools.SlashTextWatcherState @@ -219,41 +217,29 @@ interface TextBlockHolder : TextHolder { } } - fun setupTextWatcher( - item: BlockView, - onMentionEvent: ((MentionEvent) -> Unit), - onSlashEvent: (SlashEvent) -> Unit, - onTextChanged: (String, Editable) -> Unit, - ) { - content.addTextChangedListener( - DefaultTextWatcher { text -> - onTextChanged(item.id, text) - } - ) - setupMentionWatcher(onMentionEvent) - setupSlashWatcher(onSlashEvent, item.getViewType()) - } - fun setupMentionWatcher( - onMentionEvent: ((MentionEvent) -> Unit) + onMentionEvent: ((MentionEvent) -> Unit), + itemProvider: () -> BlockView.Text? ) { content.addTextChangedListener( MentionTextWatcher { state -> - when (state) { - is MentionTextWatcher.MentionTextWatcherState.Start -> { - onMentionEvent.invoke( - MentionEvent.MentionSuggestStart( - cursorCoordinate = content.cursorYBottomCoordinate(), - mentionStart = state.start + itemProvider().performInEditMode { item -> + when (state) { + is MentionTextWatcher.MentionTextWatcherState.Start -> { + onMentionEvent.invoke( + MentionEvent.MentionSuggestStart( + cursorCoordinate = content.cursorYBottomCoordinate(), + mentionStart = state.start + ) ) - ) - } - MentionTextWatcher.MentionTextWatcherState.Stop -> { - onMentionEvent.invoke(MentionEvent.MentionSuggestStop) - } + } + MentionTextWatcher.MentionTextWatcherState.Stop -> { + onMentionEvent.invoke(MentionEvent.MentionSuggestStop) + } - is MentionTextWatcher.MentionTextWatcherState.Text -> { - onMentionEvent.invoke(MentionEvent.MentionSuggestText(state.text)) + is MentionTextWatcher.MentionTextWatcherState.Text -> { + onMentionEvent.invoke(MentionEvent.MentionSuggestText(state.text)) + } } } } @@ -262,24 +248,26 @@ interface TextBlockHolder : TextHolder { fun setupSlashWatcher( onSlashEvent: (SlashEvent) -> Unit, - viewType: Int + itemProvider: () -> BlockView.Text? ) { content.addTextChangedListener( SlashTextWatcher { state -> - when (state) { - is SlashTextWatcherState.Start -> onSlashEvent( - SlashEvent.Start( - slashStart = state.start, - cursorCoordinate = content.cursorYBottomCoordinate() + itemProvider().performInEditMode { item -> + when (state) { + is SlashTextWatcherState.Start -> onSlashEvent( + SlashEvent.Start( + slashStart = state.start, + cursorCoordinate = content.cursorYBottomCoordinate() + ) ) - ) - SlashTextWatcherState.Stop -> onSlashEvent(SlashEvent.Stop) - is SlashTextWatcherState.Filter -> onSlashEvent( - SlashEvent.Filter( - filter = state.text, - viewType = viewType + SlashTextWatcherState.Stop -> onSlashEvent(SlashEvent.Stop) + is SlashTextWatcherState.Filter -> onSlashEvent( + SlashEvent.Filter( + filter = state.text, + viewType = item.getViewType() + ) ) - ) + } } } ) @@ -289,11 +277,7 @@ interface TextBlockHolder : TextHolder { fun processChangePayload( payloads: List, item: BlockView, - onTextChanged: (BlockView.Text) -> Unit, - onSelectionChanged: (String, IntRange) -> Unit, clicked: (ListenerType) -> Unit, - onMentionEvent: (MentionEvent) -> Unit, - onSlashEvent: (SlashEvent) -> Unit ) = payloads.forEach { payload -> check(item is BlockView.Text) @@ -347,19 +331,6 @@ interface TextBlockHolder : TextHolder { if (payload.readWriteModeChanged()) { content.pauseTextWatchers { if (item.mode == BlockView.Mode.EDIT) { - content.clearTextWatchers() - setupTextWatcher( - item = item, - onTextChanged = { _, editable -> - item.apply { - text = editable.toString() - marks = editable.marks() - } - onTextChanged(item) - }, - onMentionEvent = onMentionEvent, - onSlashEvent = onSlashEvent - ) //content.selectionWatcher = { onSelectionChanged(item.id, it) } content.pauseTextWatchers { enableEditMode() @@ -392,10 +363,6 @@ interface TextBlockHolder : TextHolder { } } - fun clearTextWatchers() { - content.clearTextWatchers() - } - fun resolveTextBlockThemedColor(color: ThemeColor): Int { return content.context.resolveThemedTextColor(color, getDefaultTextColor()) } @@ -500,4 +467,12 @@ interface TextBlockHolder : TextHolder { } //endregion +} + +fun BlockView.Text?.performInEditMode(block: (BlockView.Text) -> Unit) { + this?.let { item -> + if (item.mode == BlockView.Mode.EDIT) { + block(item) + } + } } \ No newline at end of file diff --git a/core-ui/src/main/java/com/anytypeio/anytype/core_ui/features/editor/holders/text/Bulleted.kt b/core-ui/src/main/java/com/anytypeio/anytype/core_ui/features/editor/holders/text/Bulleted.kt index faf754db67..fd1da9adc9 100644 --- a/core-ui/src/main/java/com/anytypeio/anytype/core_ui/features/editor/holders/text/Bulleted.kt +++ b/core-ui/src/main/java/com/anytypeio/anytype/core_ui/features/editor/holders/text/Bulleted.kt @@ -1,7 +1,6 @@ package com.anytypeio.anytype.core_ui.features.editor.holders.text import android.graphics.drawable.Drawable -import android.text.Editable import android.view.View import android.widget.FrameLayout import androidx.core.content.ContextCompat @@ -17,18 +16,15 @@ import com.anytypeio.anytype.core_ui.extensions.dark 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_ui.features.editor.marks import com.anytypeio.anytype.core_ui.widgets.text.TextInputWidget import com.anytypeio.anytype.core_utils.ext.dimen import com.anytypeio.anytype.presentation.editor.editor.listener.ListenerType -import com.anytypeio.anytype.presentation.editor.editor.mention.MentionEvent import com.anytypeio.anytype.presentation.editor.editor.model.BlockView -import com.anytypeio.anytype.presentation.editor.editor.slash.SlashEvent class Bulleted( val binding: ItemBlockBulletedBinding, clicked: (ListenerType) -> Unit, -) : Text(binding.root, clicked), SupportNesting, DecoratableViewHolder { +) : Text(binding.root, clicked), SupportNesting, DecoratableViewHolder { val indent: View = binding.bulletIndent val bullet = binding.bullet @@ -75,33 +71,6 @@ class Bulleted( } } - fun bind( - item: BlockView.Text.Bulleted, - onTextBlockTextChanged: (BlockView.Text) -> Unit, - onMentionEvent: (MentionEvent) -> Unit, - onSlashEvent: (SlashEvent) -> Unit, - onSplitLineEnterClicked: (String, Editable, IntRange) -> Unit, - onEmptyBlockBackspaceClicked: (String) -> Unit, - onNonEmptyBlockBackspaceClicked: (String, Editable) -> Unit, - onBackPressedCallback: () -> Boolean - ) = super.bind( - item = item, - onTextChanged = { _, editable -> - item.apply { - text = editable.toString() - marks = editable.marks() - } - onTextBlockTextChanged(item) - }, - onEmptyBlockBackspaceClicked = onEmptyBlockBackspaceClicked, - onSplitLineEnterClicked = onSplitLineEnterClicked, - onNonEmptyBlockBackspaceClicked = onNonEmptyBlockBackspaceClicked, - onBackPressedCallback = onBackPressedCallback - ).also { - setupMentionWatcher(onMentionEvent) - setupSlashWatcher(onSlashEvent, item.getViewType()) - } - override fun getMentionIconSize(): Int = mentionIconSize override fun getMentionIconPadding(): Int = mentionIconPadding override fun getMentionCheckedIcon(): Drawable? = mentionCheckedIcon diff --git a/core-ui/src/main/java/com/anytypeio/anytype/core_ui/features/editor/holders/text/Callout.kt b/core-ui/src/main/java/com/anytypeio/anytype/core_ui/features/editor/holders/text/Callout.kt index d18dfcf79f..3872c9e199 100644 --- a/core-ui/src/main/java/com/anytypeio/anytype/core_ui/features/editor/holders/text/Callout.kt +++ b/core-ui/src/main/java/com/anytypeio/anytype/core_ui/features/editor/holders/text/Callout.kt @@ -30,7 +30,7 @@ import com.anytypeio.anytype.presentation.editor.editor.slash.SlashEvent class Callout( val binding: ItemBlockCalloutBinding, clicked: (ListenerType) -> Unit, -) : Text( +) : Text ( view = binding.root, clicked = clicked ), BlockViewHolder.IndentableHolder, SupportNesting, DecoratableViewHolder { @@ -63,45 +63,21 @@ class Callout( } } - fun bind( - item: BlockView.Text.Callout, - onTextBlockTextChanged: (BlockView.Text) -> Unit, - onMentionEvent: (MentionEvent) -> Unit, - onSlashEvent: (SlashEvent) -> Unit, - onSplitLineEnterClicked: (String, Editable, IntRange) -> Unit, - onEmptyBlockBackspaceClicked: (String) -> Unit, - onNonEmptyBlockBackspaceClicked: (String, Editable) -> Unit, - onBackPressedCallback: () -> Boolean + override fun bind( + item: BlockView.Text.Callout ) = super.bind( - item = item, - onTextChanged = { _, editable -> - item.apply { - text = editable.toString() - marks = editable.marks() - } - onTextBlockTextChanged(item) - }, - onEmptyBlockBackspaceClicked = onEmptyBlockBackspaceClicked, - onSplitLineEnterClicked = onSplitLineEnterClicked, - onNonEmptyBlockBackspaceClicked = onNonEmptyBlockBackspaceClicked, - onBackPressedCallback = onBackPressedCallback + item = item ).also { icon.setIcon(item.icon) icon.setOnClickListener { clicked(ListenerType.Callout.Icon(item.id)) } - setupMentionWatcher(onMentionEvent) - setupSlashWatcher(onSlashEvent, item.getViewType()) } override fun processChangePayload( payloads: List, item: BlockView, - onTextChanged: (BlockView.Text) -> Unit, - onSelectionChanged: (String, IntRange) -> Unit, clicked: (ListenerType) -> Unit, - onMentionEvent: (MentionEvent) -> Unit, - onSlashEvent: (SlashEvent) -> Unit ) { val callout = requireNotNull(item as? BlockView.Text.Callout) { "Failed to processChangePayload. $item must be Callout" @@ -114,11 +90,7 @@ class Callout( super.processChangePayload( payloads, item, - onTextChanged, - onSelectionChanged, clicked, - onMentionEvent, - onSlashEvent ) } diff --git a/core-ui/src/main/java/com/anytypeio/anytype/core_ui/features/editor/holders/text/Checkbox.kt b/core-ui/src/main/java/com/anytypeio/anytype/core_ui/features/editor/holders/text/Checkbox.kt index 084d7e5d95..3471b9dfe3 100644 --- a/core-ui/src/main/java/com/anytypeio/anytype/core_ui/features/editor/holders/text/Checkbox.kt +++ b/core-ui/src/main/java/com/anytypeio/anytype/core_ui/features/editor/holders/text/Checkbox.kt @@ -1,7 +1,6 @@ package com.anytypeio.anytype.core_ui.features.editor.holders.text import android.graphics.drawable.Drawable -import android.text.Editable import android.view.View import android.widget.FrameLayout import android.widget.ImageView @@ -15,20 +14,18 @@ import com.anytypeio.anytype.core_ui.databinding.ItemBlockCheckboxBinding 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_ui.features.editor.marks +import com.anytypeio.anytype.core_ui.features.editor.performInEditMode +import com.anytypeio.anytype.core_ui.features.editor.provide import com.anytypeio.anytype.core_ui.widgets.text.TextInputWidget import com.anytypeio.anytype.core_utils.ext.dimen import com.anytypeio.anytype.presentation.editor.editor.listener.ListenerType -import com.anytypeio.anytype.presentation.editor.editor.mention.MentionEvent import com.anytypeio.anytype.presentation.editor.editor.model.BlockView -import com.anytypeio.anytype.presentation.editor.editor.slash.SlashEvent class Checkbox( val binding: ItemBlockCheckboxBinding, - clicked: (ListenerType) -> Unit, -) : Text(binding.root, clicked), SupportNesting, DecoratableViewHolder { - - var mode = BlockView.Mode.EDIT + clicked: (ListenerType) -> Unit +) : Text(binding.root, clicked), SupportNesting, + DecoratableViewHolder { val checkbox: ImageView = binding.checkboxIcon private val container = binding.graphicPlusTextContainer @@ -74,42 +71,18 @@ class Checkbox( } } - fun bind( + override fun bind( item: BlockView.Text.Checkbox, - onTextBlockTextChanged: (BlockView.Text) -> Unit, - onCheckboxClicked: (BlockView.Text.Checkbox) -> Unit, - onMentionEvent: (MentionEvent) -> Unit, - onSlashEvent: (SlashEvent) -> Unit, - onSplitLineEnterClicked: (String, Editable, IntRange) -> Unit, - onEmptyBlockBackspaceClicked: (String) -> Unit, - onNonEmptyBlockBackspaceClicked: (String, Editable) -> Unit, - onBackPressedCallback: () -> Boolean - ) = super.bind( - item = item, - onTextChanged = { _, editable -> - item.apply { - text = editable.toString() - marks = editable.marks() - } - onTextBlockTextChanged(item) - }, - onEmptyBlockBackspaceClicked = onEmptyBlockBackspaceClicked, - onSplitLineEnterClicked = onSplitLineEnterClicked, - onNonEmptyBlockBackspaceClicked = onNonEmptyBlockBackspaceClicked, - onBackPressedCallback = onBackPressedCallback - ).also { + ) = super.bind(item = item).also { checkbox.isActivated = item.isChecked - setCheckboxClickListener(item, onCheckboxClicked) - setupMentionWatcher(onMentionEvent) - setupSlashWatcher(onSlashEvent, item.getViewType()) } - private fun setCheckboxClickListener( - item: BlockView.Text.Checkbox, + fun setCheckboxClickListener( onCheckboxClicked: (BlockView.Text.Checkbox) -> Unit ) { checkbox.setOnClickListener { - if (mode == BlockView.Mode.EDIT) { + val item = provide() ?: return@setOnClickListener + item.performInEditMode { item.isChecked = !item.isChecked checkbox.isActivated = !checkbox.isActivated applyCheckedCheckboxColorSpan(item.isChecked) @@ -130,16 +103,6 @@ class Checkbox( } } - override fun enableEditMode() { - super.enableEditMode() - mode = BlockView.Mode.EDIT - } - - override fun enableReadMode() { - super.enableReadMode() - mode = BlockView.Mode.READ - } - override fun select(item: BlockView.Selectable) { container.isSelected = item.isSelected } diff --git a/core-ui/src/main/java/com/anytypeio/anytype/core_ui/features/editor/holders/text/Header.kt b/core-ui/src/main/java/com/anytypeio/anytype/core_ui/features/editor/holders/text/Header.kt index 163c9e7b4c..970ceaffd4 100644 --- a/core-ui/src/main/java/com/anytypeio/anytype/core_ui/features/editor/holders/text/Header.kt +++ b/core-ui/src/main/java/com/anytypeio/anytype/core_ui/features/editor/holders/text/Header.kt @@ -1,6 +1,5 @@ package com.anytypeio.anytype.core_ui.features.editor.holders.text -import android.text.Editable import android.view.View import androidx.core.view.updatePadding import com.anytypeio.anytype.core_ui.BuildConfig @@ -8,52 +7,21 @@ import com.anytypeio.anytype.core_ui.R import com.anytypeio.anytype.core_ui.features.editor.BlockViewHolder import com.anytypeio.anytype.core_ui.features.editor.TextBlockHolder import com.anytypeio.anytype.core_ui.features.editor.decoration.DecoratableViewHolder -import com.anytypeio.anytype.core_ui.features.editor.marks import com.anytypeio.anytype.core_ui.widgets.text.TextInputWidget import com.anytypeio.anytype.core_utils.ext.dimen import com.anytypeio.anytype.presentation.editor.editor.listener.ListenerType -import com.anytypeio.anytype.presentation.editor.editor.mention.MentionEvent import com.anytypeio.anytype.presentation.editor.editor.model.BlockView -import com.anytypeio.anytype.presentation.editor.editor.slash.SlashEvent -abstract class Header( +abstract class Header( view: View, clicked: (ListenerType) -> Unit, -) : Text(view, clicked), +) : Text(view, clicked), TextBlockHolder, BlockViewHolder.IndentableHolder, - DecoratableViewHolder -{ + DecoratableViewHolder { abstract val header: TextInputWidget - fun bind( - block: BlockView.Text.Header, - onTextBlockTextChanged: (BlockView.Text) -> Unit, - onMentionEvent: (MentionEvent) -> Unit, - onSlashEvent: (SlashEvent) -> Unit, - onSplitLineEnterClicked: (String, Editable, IntRange) -> Unit, - onEmptyBlockBackspaceClicked: (String) -> Unit, - onNonEmptyBlockBackspaceClicked: (String, Editable) -> Unit, - onBackPressedCallback: () -> Boolean - ) = super.bind( - item = block, - onTextChanged = { _, editable -> - block.apply { - text = editable.toString() - marks = editable.marks() - } - onTextBlockTextChanged(block) - }, - onEmptyBlockBackspaceClicked = onEmptyBlockBackspaceClicked, - onSplitLineEnterClicked = onSplitLineEnterClicked, - onNonEmptyBlockBackspaceClicked = onNonEmptyBlockBackspaceClicked, - onBackPressedCallback = onBackPressedCallback - ).also { - setupMentionWatcher(onMentionEvent) - setupSlashWatcher(onSlashEvent, block.getViewType()) - } - override fun indentize(item: BlockView.Indentable) { if (!BuildConfig.NESTED_DECORATION_ENABLED) { header.updatePadding( diff --git a/core-ui/src/main/java/com/anytypeio/anytype/core_ui/features/editor/holders/text/HeaderOne.kt b/core-ui/src/main/java/com/anytypeio/anytype/core_ui/features/editor/holders/text/HeaderOne.kt index 961cf1f929..bf986e9f45 100644 --- a/core-ui/src/main/java/com/anytypeio/anytype/core_ui/features/editor/holders/text/HeaderOne.kt +++ b/core-ui/src/main/java/com/anytypeio/anytype/core_ui/features/editor/holders/text/HeaderOne.kt @@ -16,7 +16,7 @@ import com.anytypeio.anytype.presentation.editor.editor.model.BlockView class HeaderOne( val binding: ItemBlockHeaderOneBinding, clicked: (ListenerType) -> Unit, -) : Header(binding.root, clicked) { +) : Header(binding.root, clicked) { override val header: TextInputWidget = binding.headerOne override val content: TextInputWidget get() = header diff --git a/core-ui/src/main/java/com/anytypeio/anytype/core_ui/features/editor/holders/text/HeaderThree.kt b/core-ui/src/main/java/com/anytypeio/anytype/core_ui/features/editor/holders/text/HeaderThree.kt index c2073a0dec..61c3a38ce0 100644 --- a/core-ui/src/main/java/com/anytypeio/anytype/core_ui/features/editor/holders/text/HeaderThree.kt +++ b/core-ui/src/main/java/com/anytypeio/anytype/core_ui/features/editor/holders/text/HeaderThree.kt @@ -16,7 +16,7 @@ import com.anytypeio.anytype.presentation.editor.editor.model.BlockView class HeaderThree( val binding: ItemBlockHeaderThreeBinding, clicked: (ListenerType) -> Unit, -) : Header(binding.root, clicked) { +) : Header(binding.root, clicked) { override val header: TextInputWidget = binding.headerThree override val content: TextInputWidget get() = header diff --git a/core-ui/src/main/java/com/anytypeio/anytype/core_ui/features/editor/holders/text/HeaderTwo.kt b/core-ui/src/main/java/com/anytypeio/anytype/core_ui/features/editor/holders/text/HeaderTwo.kt index 53c718121f..83e2f10990 100644 --- a/core-ui/src/main/java/com/anytypeio/anytype/core_ui/features/editor/holders/text/HeaderTwo.kt +++ b/core-ui/src/main/java/com/anytypeio/anytype/core_ui/features/editor/holders/text/HeaderTwo.kt @@ -16,7 +16,7 @@ import com.anytypeio.anytype.presentation.editor.editor.model.BlockView class HeaderTwo( val binding: ItemBlockHeaderTwoBinding, clicked: (ListenerType) -> Unit, -) : Header(binding.root, clicked) { +) : Header(binding.root, clicked) { override val header: TextInputWidget = binding.headerTwo override val content: TextInputWidget get() = header diff --git a/core-ui/src/main/java/com/anytypeio/anytype/core_ui/features/editor/holders/text/Highlight.kt b/core-ui/src/main/java/com/anytypeio/anytype/core_ui/features/editor/holders/text/Highlight.kt index 55f6553c48..48b92a6663 100644 --- a/core-ui/src/main/java/com/anytypeio/anytype/core_ui/features/editor/holders/text/Highlight.kt +++ b/core-ui/src/main/java/com/anytypeio/anytype/core_ui/features/editor/holders/text/Highlight.kt @@ -27,7 +27,7 @@ import com.anytypeio.anytype.presentation.editor.editor.slash.SlashEvent class Highlight( val binding: ItemBlockHighlightBinding, clicked: (ListenerType) -> Unit, -) : Text(binding.root, clicked), BlockViewHolder.IndentableHolder, SupportNesting, DecoratableViewHolder { +) : Text(binding.root, clicked), BlockViewHolder.IndentableHolder, SupportNesting, DecoratableViewHolder { override val content: TextInputWidget = binding.highlightContent override val root: View = itemView @@ -75,34 +75,6 @@ class Highlight( } } - fun bind( - item: BlockView.Text.Highlight, - onTextBlockTextChanged: (BlockView.Text) -> Unit, - clicked: (ListenerType) -> Unit, - onMentionEvent: (MentionEvent) -> Unit, - onSlashEvent: (SlashEvent) -> Unit, - onSplitLineEnterClicked: (String, Editable, IntRange) -> Unit, - onEmptyBlockBackspaceClicked: (String) -> Unit, - onNonEmptyBlockBackspaceClicked: (String, Editable) -> Unit, - onBackPressedCallback: () -> Boolean - ) = super.bind( - item = item, - onTextChanged = { _, editable -> - item.apply { - text = editable.toString() - marks = editable.marks() - } - onTextBlockTextChanged(item) - }, - onEmptyBlockBackspaceClicked = onEmptyBlockBackspaceClicked, - onSplitLineEnterClicked = onSplitLineEnterClicked, - onNonEmptyBlockBackspaceClicked = onNonEmptyBlockBackspaceClicked, - onBackPressedCallback = onBackPressedCallback - ).also { - setupMentionWatcher(onMentionEvent) - setupSlashWatcher(onSlashEvent, item.getViewType()) - } - override fun select(item: BlockView.Selectable) { container.isSelected = item.isSelected } diff --git a/core-ui/src/main/java/com/anytypeio/anytype/core_ui/features/editor/holders/text/Numbered.kt b/core-ui/src/main/java/com/anytypeio/anytype/core_ui/features/editor/holders/text/Numbered.kt index a6c0dd0ae9..c26a4b5e8c 100644 --- a/core-ui/src/main/java/com/anytypeio/anytype/core_ui/features/editor/holders/text/Numbered.kt +++ b/core-ui/src/main/java/com/anytypeio/anytype/core_ui/features/editor/holders/text/Numbered.kt @@ -1,7 +1,6 @@ package com.anytypeio.anytype.core_ui.features.editor.holders.text import android.graphics.drawable.Drawable -import android.text.Editable import android.view.Gravity import android.view.View import android.widget.FrameLayout @@ -19,7 +18,6 @@ import com.anytypeio.anytype.core_ui.features.editor.BlockViewDiffUtil 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_ui.features.editor.marks import com.anytypeio.anytype.core_ui.widgets.text.TextInputWidget import com.anytypeio.anytype.core_utils.ext.addDot import com.anytypeio.anytype.core_utils.ext.dimen @@ -31,7 +29,7 @@ import com.anytypeio.anytype.presentation.editor.editor.slash.SlashEvent class Numbered( val binding: ItemBlockNumberedBinding, clicked: (ListenerType) -> Unit, -) : Text(binding.root, clicked), SupportNesting, DecoratableViewHolder { +) : Text(binding.root, clicked), SupportNesting, DecoratableViewHolder { private val container = binding.graphicPlusTextContainer val number = binding.number @@ -77,32 +75,10 @@ class Numbered( } } - fun bind( - item: BlockView.Text.Numbered, - onTextBlockTextChanged: (BlockView.Text) -> Unit, - onMentionEvent: (MentionEvent) -> Unit, - onSlashEvent: (SlashEvent) -> Unit, - onSplitLineEnterClicked: (String, Editable, IntRange) -> Unit, - onEmptyBlockBackspaceClicked: (String) -> Unit, - onNonEmptyBlockBackspaceClicked: (String, Editable) -> Unit, - onBackPressedCallback: () -> Boolean - ) = super.bind( - item = item, - onTextChanged = { _, editable -> - item.apply { - text = editable.toString() - marks = editable.marks() - } - onTextBlockTextChanged(item) - }, - onEmptyBlockBackspaceClicked = onEmptyBlockBackspaceClicked, - onSplitLineEnterClicked = onSplitLineEnterClicked, - onNonEmptyBlockBackspaceClicked = onNonEmptyBlockBackspaceClicked, - onBackPressedCallback = onBackPressedCallback - ).also { + override fun bind( + item: BlockView.Text.Numbered + ) = super.bind(item = item).also { setNumber(item) - setupMentionWatcher(onMentionEvent) - setupSlashWatcher(onSlashEvent, item.getViewType()) } private fun setNumber(item: BlockView.Text.Numbered) { @@ -122,20 +98,12 @@ class Numbered( override fun processChangePayload( payloads: List, item: BlockView, - onTextChanged: (BlockView.Text) -> Unit, - onSelectionChanged: (String, IntRange) -> Unit, - clicked: (ListenerType) -> Unit, - onMentionEvent: (MentionEvent) -> Unit, - onSlashEvent: (SlashEvent) -> Unit + clicked: (ListenerType) -> Unit ) { super.processChangePayload( payloads, item, - onTextChanged, - onSelectionChanged, - clicked, - onMentionEvent, - onSlashEvent + clicked ) payloads.forEach { payload -> if (payload.changes.contains(BlockViewDiffUtil.NUMBER_CHANGED)) diff --git a/core-ui/src/main/java/com/anytypeio/anytype/core_ui/features/editor/holders/text/Paragraph.kt b/core-ui/src/main/java/com/anytypeio/anytype/core_ui/features/editor/holders/text/Paragraph.kt index 87a889e2d1..4731ac238f 100644 --- a/core-ui/src/main/java/com/anytypeio/anytype/core_ui/features/editor/holders/text/Paragraph.kt +++ b/core-ui/src/main/java/com/anytypeio/anytype/core_ui/features/editor/holders/text/Paragraph.kt @@ -25,7 +25,7 @@ import com.anytypeio.anytype.presentation.editor.editor.slash.SlashEvent class Paragraph( val binding: ItemBlockTextBinding, clicked: (ListenerType) -> Unit, -) : Text(binding.root, clicked), SupportNesting, DecoratableViewHolder { +) : Text(binding.root, clicked), SupportNesting, DecoratableViewHolder { override val root: View = binding.root override val content: TextInputWidget = binding.textContent @@ -64,33 +64,6 @@ class Paragraph( } } - fun bind( - item: BlockView.Text.Paragraph, - onTextBlockTextChanged: (BlockView.Text) -> Unit, - onMentionEvent: (MentionEvent) -> Unit, - onSlashEvent: (SlashEvent) -> Unit, - onSplitLineEnterClicked: (String, Editable, IntRange) -> Unit, - onEmptyBlockBackspaceClicked: (String) -> Unit, - onNonEmptyBlockBackspaceClicked: (String, Editable) -> Unit, - onBackPressedCallback: () -> Boolean - ) = super.bind( - item = item, - onTextChanged = { _, editable -> - item.apply { - text = editable.toString() - marks = editable.marks() - } - onTextBlockTextChanged(item) - }, - onEmptyBlockBackspaceClicked = onEmptyBlockBackspaceClicked, - onSplitLineEnterClicked = onSplitLineEnterClicked, - onNonEmptyBlockBackspaceClicked = onNonEmptyBlockBackspaceClicked, - onBackPressedCallback = onBackPressedCallback - ).also { - setupMentionWatcher(onMentionEvent) - setupSlashWatcher(onSlashEvent, item.getViewType()) - } - override fun getMentionIconSize(): Int = mentionIconSize override fun getMentionIconPadding(): Int = mentionIconPadding override fun getMentionCheckedIcon(): Drawable? = mentionCheckedIcon diff --git a/core-ui/src/main/java/com/anytypeio/anytype/core_ui/features/editor/holders/text/Text.kt b/core-ui/src/main/java/com/anytypeio/anytype/core_ui/features/editor/holders/text/Text.kt index 4cd38a643c..8c1f2a9e14 100644 --- a/core-ui/src/main/java/com/anytypeio/anytype/core_ui/features/editor/holders/text/Text.kt +++ b/core-ui/src/main/java/com/anytypeio/anytype/core_ui/features/editor/holders/text/Text.kt @@ -2,31 +2,31 @@ package com.anytypeio.anytype.core_ui.features.editor.holders.text import android.text.Editable import android.view.View +import androidx.annotation.CallSuper import com.anytypeio.anytype.core_ui.R import com.anytypeio.anytype.core_ui.extensions.applyMovementMethod -import com.anytypeio.anytype.core_ui.extensions.color import com.anytypeio.anytype.core_ui.features.editor.BlockViewHolder import com.anytypeio.anytype.core_ui.features.editor.TextBlockHolder +import com.anytypeio.anytype.core_ui.features.editor.performInEditMode +import com.anytypeio.anytype.core_ui.features.editor.provide +import com.anytypeio.anytype.core_ui.features.editor.withBlock import com.anytypeio.anytype.core_ui.tools.DefaultTextWatcher import com.anytypeio.anytype.presentation.editor.editor.listener.ListenerType +import com.anytypeio.anytype.presentation.editor.editor.mention.MentionEvent import com.anytypeio.anytype.presentation.editor.editor.model.BlockView import com.anytypeio.anytype.presentation.editor.editor.model.Checkable +import com.anytypeio.anytype.presentation.editor.editor.slash.SlashEvent -abstract class Text( +abstract class Text( view: View, - protected val clicked: (ListenerType) -> Unit, + protected val clicked: (ListenerType) -> Unit ) : BlockViewHolder(view), TextBlockHolder, BlockViewHolder.IndentableHolder, BlockViewHolder.DragAndDropHolder { private val defTextColor: Int = itemView.context.resources.getColor(R.color.text_primary, null) - fun bind( - item: BlockView.TextBlockProps, - onTextChanged: (String, Editable) -> Unit, - onSplitLineEnterClicked: (String, Editable, IntRange) -> Unit, - onEmptyBlockBackspaceClicked: (String) -> Unit, - onNonEmptyBlockBackspaceClicked: (String, Editable) -> Unit, - onBackPressedCallback: (() -> Boolean)? = null + open fun bind( + item: BlockTextType, ) { indentize(item) select(item) @@ -47,8 +47,6 @@ abstract class Text( content.applyMovementMethod(item) - clearTextWatchers() - setContent( item = item, clicked = clicked @@ -58,39 +56,6 @@ abstract class Text( if (item.isFocused) setCursor(item) setFocus(item) - - observe( - item = item, - onTextChanged = onTextChanged, - onBackPressedCallback = onBackPressedCallback - ) - } - - content.apply { - enableEnterKeyDetector( - onEnterClicked = { range -> - content.text?.let { editable -> - onSplitLineEnterClicked( - item.id, - editable, - range - ) - } - } - ) - enableBackspaceDetector( - onEmptyBlockBackspaceClicked = { - onEmptyBlockBackspaceClicked(item.id) - }, - onNonEmptyBlockBackspaceClicked = { - content.text?.let { editable -> - onNonEmptyBlockBackspaceClicked( - item.id, - editable - ) - } - } - ) } } @@ -119,16 +84,16 @@ abstract class Text( setBackgroundColor(background = item.background) } - fun observe( - item: BlockView.TextBlockProps, - onTextChanged: (String, Editable) -> Unit, + private fun observe( + onTextChanged: (Editable) -> Unit, onBackPressedCallback: (() -> Boolean)? = null ) { - content.apply { addTextChangedListener( DefaultTextWatcher { text -> - onTextChanged(item.id, text) + provide().performInEditMode { item -> + onTextChanged(text) + } } ) backButtonWatcher = onBackPressedCallback @@ -144,4 +109,47 @@ abstract class Text( } override fun getDefaultTextColor(): Int = defTextColor + + @CallSuper + open fun setupViewHolder( + onTextChanged: (Editable) -> Unit, + onSplitLineEnterClicked: (String, Editable, IntRange) -> Unit, + onEmptyBlockBackspaceClicked: (String) -> Unit, + onNonEmptyBlockBackspaceClicked: (String, Editable) -> Unit, + onMentionEvent: ((MentionEvent) -> Unit), + onSlashEvent: (SlashEvent) -> Unit, + onBackPressedCallback: (() -> Boolean)? = null + ) { + observe(onTextChanged, onBackPressedCallback) + + content.apply { + enableEnterKeyDetector( + onEnterClicked = { range -> + val id = provide()?.id ?: return@enableEnterKeyDetector + val editable = content.text ?: return@enableEnterKeyDetector + onSplitLineEnterClicked( + id, + editable, + range + ) + } + ) + enableBackspaceDetector( + onEmptyBlockBackspaceClicked = { + val id = provide()?.id ?: return@enableBackspaceDetector + onEmptyBlockBackspaceClicked(id) + }, + onNonEmptyBlockBackspaceClicked = { + val id = provide()?.id ?: return@enableBackspaceDetector + val editable = content.text ?: return@enableBackspaceDetector + onNonEmptyBlockBackspaceClicked( + id, + editable + ) + } + ) + } + setupMentionWatcher(onMentionEvent) { provide() } + setupSlashWatcher(onSlashEvent) { provide() } + } } \ No newline at end of file diff --git a/core-ui/src/main/java/com/anytypeio/anytype/core_ui/features/editor/holders/text/Toggle.kt b/core-ui/src/main/java/com/anytypeio/anytype/core_ui/features/editor/holders/text/Toggle.kt index 42c9dc020c..7e002c71c1 100644 --- a/core-ui/src/main/java/com/anytypeio/anytype/core_ui/features/editor/holders/text/Toggle.kt +++ b/core-ui/src/main/java/com/anytypeio/anytype/core_ui/features/editor/holders/text/Toggle.kt @@ -1,7 +1,6 @@ package com.anytypeio.anytype.core_ui.features.editor.holders.text import android.graphics.drawable.Drawable -import android.text.Editable import android.view.View import android.widget.FrameLayout import androidx.core.content.ContextCompat @@ -16,7 +15,7 @@ import com.anytypeio.anytype.core_ui.features.editor.BlockViewDiffUtil 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_ui.features.editor.marks +import com.anytypeio.anytype.core_ui.features.editor.provide import com.anytypeio.anytype.core_ui.widgets.text.TextInputWidget import com.anytypeio.anytype.core_utils.ext.dimen import com.anytypeio.anytype.presentation.editor.editor.listener.ListenerType @@ -27,7 +26,7 @@ import com.anytypeio.anytype.presentation.editor.editor.slash.SlashEvent class Toggle( val binding: ItemBlockToggleBinding, clicked: (ListenerType) -> Unit, -) : Text(binding.root, clicked), SupportNesting, DecoratableViewHolder { +) : Text(binding.root, clicked), SupportNesting, DecoratableViewHolder { private var mode = BlockView.Mode.EDIT @@ -77,41 +76,29 @@ class Toggle( } } - fun bind( - item: BlockView.Text.Toggle, - onTextBlockTextChanged: (BlockView.Text) -> Unit, - onToggleClicked: (String) -> Unit, - onTogglePlaceholderClicked: (String) -> Unit, - onMentionEvent: (MentionEvent) -> Unit, - onSlashEvent: (SlashEvent) -> Unit, - onSplitLineEnterClicked: (String, Editable, IntRange) -> Unit, - onEmptyBlockBackspaceClicked: (String) -> Unit, - onNonEmptyBlockBackspaceClicked: (String, Editable) -> Unit, - onBackPressedCallback: () -> Boolean - ) = super.bind( - item = item, - onTextChanged = { _, editable -> - item.apply { - text = editable.toString() - marks = editable.marks() - } - onTextBlockTextChanged(item) - }, - onEmptyBlockBackspaceClicked = onEmptyBlockBackspaceClicked, - onSplitLineEnterClicked = onSplitLineEnterClicked, - onNonEmptyBlockBackspaceClicked = onNonEmptyBlockBackspaceClicked, - onBackPressedCallback = onBackPressedCallback - ).also { + override fun bind( + item: BlockView.Text.Toggle + ) = super.bind(item = item).also { toggle.rotation = if (item.toggled) EXPANDED_ROTATION else COLLAPSED_ROTATION if (item.mode == BlockView.Mode.READ) { placeholder.isVisible = false } else { placeholder.isVisible = item.isEmpty && item.toggled } - placeholder.setOnClickListener { onTogglePlaceholderClicked(item.id) } - toggle.setOnClickListener { onToggleClicked(item.id) } - setupMentionWatcher(onMentionEvent) - setupSlashWatcher(onSlashEvent, item.getViewType()) + } + + fun setupToggle( + onToggleClicked: (String) -> Unit, + onTogglePlaceholderClicked: (String) -> Unit + ) { + placeholder.setOnClickListener { + val id = provide()?.id ?: return@setOnClickListener + onTogglePlaceholderClicked(id) + } + toggle.setOnClickListener { + val id = provide()?.id ?: return@setOnClickListener + onToggleClicked(id) + } } override fun getMentionIconSize(): Int = mentionIconSize @@ -143,21 +130,13 @@ class Toggle( override fun processChangePayload( payloads: List, item: BlockView, - onTextChanged: (BlockView.Text) -> Unit, - onSelectionChanged: (String, IntRange) -> Unit, - clicked: (ListenerType) -> Unit, - onMentionEvent: (MentionEvent) -> Unit, - onSlashEvent: (SlashEvent) -> Unit + clicked: (ListenerType) -> Unit ) { check(item is BlockView.Text.Toggle) { "Expected a toggle block, but was: $item" } super.processChangePayload( payloads, item, - onTextChanged, - onSelectionChanged, clicked, - onMentionEvent, - onSlashEvent ) payloads.forEach { payload -> if (payload.isToggleStateChanged) { diff --git a/core-ui/src/test/java/com/anytypeio/anytype/core_ui/BlockAdapterTest.kt b/core-ui/src/test/java/com/anytypeio/anytype/core_ui/BlockAdapterTest.kt index 27fb759fb3..c22f0f3b09 100644 --- a/core-ui/src/test/java/com/anytypeio/anytype/core_ui/BlockAdapterTest.kt +++ b/core-ui/src/test/java/com/anytypeio/anytype/core_ui/BlockAdapterTest.kt @@ -119,7 +119,7 @@ class BlockAdapterTest { val views = listOf(paragraph) - val adapter = buildAdapter(views) + val adapter = givenAdapter(views) val recycler = RecyclerView(context).apply { layoutManager = LinearLayoutManager(context) @@ -145,7 +145,7 @@ class BlockAdapterTest { val views = listOf(paragraph) - val adapter = buildAdapter(views) + val adapter = givenAdapter(views) val recycler = RecyclerView(context).apply { layoutManager = LinearLayoutManager(context) @@ -180,7 +180,7 @@ class BlockAdapterTest { val views = listOf(paragraph) - val adapter = buildAdapter(views) + val adapter = givenAdapter(views) val recycler = RecyclerView(context).apply { layoutManager = LinearLayoutManager(context) @@ -218,7 +218,7 @@ class BlockAdapterTest { val views = listOf(paragraph) - val adapter = buildAdapter(views) + val adapter = givenAdapter(views) val recycler = RecyclerView(context).apply { layoutManager = LinearLayoutManager(context) @@ -244,11 +244,7 @@ class BlockAdapterTest { changes = listOf(TEXT_CHANGED) ) ), - onSelectionChanged = { _, _ -> }, - onTextChanged = {}, clicked = {}, - onMentionEvent = {}, - onSlashEvent = {} ) assertEquals( @@ -275,7 +271,7 @@ class BlockAdapterTest { val views = listOf(paragraph) - val adapter = buildAdapter(views) + val adapter = givenAdapter(views) val recycler = RecyclerView(context).apply { layoutManager = LinearLayoutManager(context) @@ -301,11 +297,7 @@ class BlockAdapterTest { changes = listOf(BACKGROUND_COLOR_CHANGED) ) ), - onSelectionChanged = { _, _ -> }, - onTextChanged = {}, clicked = {}, - onMentionEvent = {}, - onSlashEvent = {} ) if (!BuildConfig.NESTED_DECORATION_ENABLED) { @@ -334,7 +326,7 @@ class BlockAdapterTest { val views = listOf(paragraph) - val adapter = buildAdapter(views) + val adapter = givenAdapter(views) val recycler = RecyclerView(context).apply { layoutManager = LinearLayoutManager(context) @@ -360,11 +352,7 @@ class BlockAdapterTest { changes = listOf(TEXT_COLOR_CHANGED) ) ), - onSelectionChanged = { _, _ -> }, - onTextChanged = {}, clicked = {}, - onMentionEvent = {}, - onSlashEvent = {} ) val expected = context.resources.getColor(R.color.palette_dark_lime) @@ -392,7 +380,7 @@ class BlockAdapterTest { val views = listOf(paragraph) - val adapter = buildAdapter(views) + val adapter = givenAdapter(views) val recycler = RecyclerView(context).apply { layoutManager = LinearLayoutManager(context) @@ -428,11 +416,7 @@ class BlockAdapterTest { changes = listOf(CURSOR_CHANGED) ) ), - onSelectionChanged = { _, _ -> }, - onTextChanged = {}, clicked = {}, - onMentionEvent = {}, - onSlashEvent = {} ) assertEquals( @@ -465,7 +449,7 @@ class BlockAdapterTest { val views = listOf(title) - val adapter = buildAdapter(views) + val adapter = givenAdapter(views) val recycler = RecyclerView(context).apply { layoutManager = LinearLayoutManager(context) @@ -518,7 +502,7 @@ class BlockAdapterTest { val views = listOf(paragraph) - val adapter = buildAdapter( + val adapter = givenAdapter( views = views, onTextChanged = { id, editable -> events.add(Pair(id, editable.toString())) @@ -561,7 +545,7 @@ class BlockAdapterTest { val views = listOf(paragraph) - val adapter = buildAdapter( + val adapter = givenAdapter( views = views, onTextChanged = { id, editable -> events.add(Pair(id, editable.toString())) @@ -587,11 +571,7 @@ class BlockAdapterTest { ) ), item = updated, - onSelectionChanged = { _, _ -> }, - onTextChanged = {}, clicked = {}, - onMentionEvent = {}, - onSlashEvent = {} ) assertEquals( @@ -611,7 +591,7 @@ class BlockAdapterTest { val views = listOf(title) - val adapter = buildAdapter(views) + val adapter = givenAdapter(views) val recycler = RecyclerView(context).apply { layoutManager = LinearLayoutManager(context) @@ -638,7 +618,7 @@ class BlockAdapterTest { val views = listOf(title) - val adapter = buildAdapter(views) + val adapter = givenAdapter(views) val recycler = RecyclerView(context).apply { layoutManager = LinearLayoutManager(context) @@ -677,7 +657,7 @@ class BlockAdapterTest { val views = listOf(title) - val adapter = buildAdapter(views) + val adapter = givenAdapter(views) val recycler = RecyclerView(context).apply { layoutManager = LinearLayoutManager(context) @@ -726,7 +706,7 @@ class BlockAdapterTest { val views = listOf(title) - val adapter = buildAdapter( + val adapter = givenAdapter( views = views, onFocusChanged = { id, hasFocus -> events.add(Pair(id, hasFocus)) @@ -775,7 +755,7 @@ class BlockAdapterTest { val views = listOf(title) - val adapter = buildAdapter( + val adapter = givenAdapter( views = views, onTextChanged = { id, editable -> events.add(Pair(id, editable.toString())) @@ -819,7 +799,7 @@ class BlockAdapterTest { layoutManager = LinearLayoutManager(context) } - val adapter = buildAdapter(views) + val adapter = givenAdapter(views) val holder = adapter.onCreateViewHolder(recycler, HOLDER_PARAGRAPH) @@ -853,7 +833,7 @@ class BlockAdapterTest { layoutManager = LinearLayoutManager(context) } - val adapter = buildAdapter(views) + val adapter = givenAdapter(views) val holder = adapter.onCreateViewHolder(recycler, Types.HOLDER_HEADER_ONE) @@ -886,7 +866,7 @@ class BlockAdapterTest { layoutManager = LinearLayoutManager(context) } - val adapter = buildAdapter(views) + val adapter = givenAdapter(views) val holder = adapter.onCreateViewHolder(recycler, Types.HOLDER_HEADER_TWO) @@ -921,7 +901,7 @@ class BlockAdapterTest { layoutManager = LinearLayoutManager(context) } - val adapter = buildAdapter(views) + val adapter = givenAdapter(views) val holder = adapter.onCreateViewHolder(recycler, Types.HOLDER_HEADER_THREE) @@ -951,7 +931,7 @@ class BlockAdapterTest { layoutManager = LinearLayoutManager(context) } - val adapter = buildAdapter(views) + val adapter = givenAdapter(views) val holder = adapter.onCreateViewHolder(recycler, Types.HOLDER_CHECKBOX) @@ -984,7 +964,7 @@ class BlockAdapterTest { layoutManager = LinearLayoutManager(context) } - val adapter = buildAdapter(views) + val adapter = givenAdapter(views) val holder = adapter.onCreateViewHolder(recycler, Types.HOLDER_TOGGLE) @@ -1013,7 +993,7 @@ class BlockAdapterTest { layoutManager = LinearLayoutManager(context) } - val adapter = buildAdapter(views) + val adapter = givenAdapter(views) val holder = adapter.onCreateViewHolder(recycler, Types.HOLDER_FILE_PLACEHOLDER) @@ -1046,7 +1026,7 @@ class BlockAdapterTest { layoutManager = LinearLayoutManager(context) } - val adapter = buildAdapter(views) + val adapter = givenAdapter(views) val holder = adapter.onCreateViewHolder(recycler, Types.HOLDER_FILE_ERROR) @@ -1075,7 +1055,7 @@ class BlockAdapterTest { layoutManager = LinearLayoutManager(context) } - val adapter = buildAdapter(views) + val adapter = givenAdapter(views) val holder = adapter.onCreateViewHolder(recycler, Types.HOLDER_FILE_UPLOAD) @@ -1102,7 +1082,7 @@ class BlockAdapterTest { layoutManager = LinearLayoutManager(context) } - val adapter = buildAdapter(views) + val adapter = givenAdapter(views) val holder = adapter.onCreateViewHolder(recycler, Types.HOLDER_VIDEO) @@ -1129,7 +1109,7 @@ class BlockAdapterTest { layoutManager = LinearLayoutManager(context) } - val adapter = buildAdapter(views) + val adapter = givenAdapter(views) val holder = adapter.onCreateViewHolder(recycler, Types.HOLDER_VIDEO_PLACEHOLDER) @@ -1161,7 +1141,7 @@ class BlockAdapterTest { layoutManager = LinearLayoutManager(context) } - val adapter = buildAdapter(views) + val adapter = givenAdapter(views) val holder = adapter.onCreateViewHolder(recycler, Types.HOLDER_VIDEO_UPLOAD) @@ -1194,7 +1174,7 @@ class BlockAdapterTest { layoutManager = LinearLayoutManager(context) } - val adapter = buildAdapter(views) + val adapter = givenAdapter(views) val holder = adapter.onCreateViewHolder(recycler, Types.HOLDER_VIDEO_ERROR) @@ -1226,7 +1206,7 @@ class BlockAdapterTest { layoutManager = LinearLayoutManager(context) } - val adapter = buildAdapter(views) + val adapter = givenAdapter(views) val holder = adapter.onCreateViewHolder(recycler, Types.HOLDER_OBJECT_LINK_DEFAULT) @@ -1252,7 +1232,7 @@ class BlockAdapterTest { layoutManager = LinearLayoutManager(context) } - val adapter = buildAdapter(views) + val adapter = givenAdapter(views) val holder = adapter.onCreateViewHolder(recycler, Types.HOLDER_BOOKMARK_PLACEHOLDER) @@ -1262,7 +1242,8 @@ class BlockAdapterTest { if (!BuildConfig.NESTED_DECORATION_ENABLED) { val actual = holder.itemView.findViewById(R.id.root).paddingLeft - val expected = view.indent * holder.dimen(R.dimen.indent) + holder.dimen(R.dimen.default_document_item_padding_start) + val expected = + view.indent * holder.dimen(R.dimen.indent) + holder.dimen(R.dimen.default_document_item_padding_start) assertEquals(expected, actual) } else { val actual = holder.itemView.findViewById(R.id.root).paddingLeft @@ -1291,7 +1272,7 @@ class BlockAdapterTest { layoutManager = LinearLayoutManager(context) } - val adapter = buildAdapter(views) + val adapter = givenAdapter(views) val holder = adapter.onCreateViewHolder(recycler, Types.HOLDER_PICTURE) @@ -1320,7 +1301,7 @@ class BlockAdapterTest { layoutManager = LinearLayoutManager(context) } - val adapter = buildAdapter(views) + val adapter = givenAdapter(views) val holder = adapter.onCreateViewHolder(recycler, Types.HOLDER_PICTURE_PLACEHOLDER) @@ -1353,7 +1334,7 @@ class BlockAdapterTest { layoutManager = LinearLayoutManager(context) } - val adapter = buildAdapter(views) + val adapter = givenAdapter(views) val holder = adapter.onCreateViewHolder(recycler, Types.HOLDER_PICTURE_ERROR) @@ -1384,7 +1365,7 @@ class BlockAdapterTest { layoutManager = LinearLayoutManager(context) } - val adapter = buildAdapter(views) + val adapter = givenAdapter(views) val holder = adapter.onCreateViewHolder(recycler, Types.HOLDER_PICTURE_UPLOAD) @@ -1394,7 +1375,8 @@ class BlockAdapterTest { if (!BuildConfig.NESTED_DECORATION_ENABLED) { val actual = holder.itemView.marginLeft - val expected = holder.dimen(R.dimen.bookmark_default_margin_start) + view.indent * holder.dimen(R.dimen.indent) + val expected = + holder.dimen(R.dimen.bookmark_default_margin_start) + view.indent * holder.dimen(R.dimen.indent) assertEquals(expected, actual) } } @@ -1416,7 +1398,7 @@ class BlockAdapterTest { val views = listOf(title) - val adapter = buildAdapter(views) + val adapter = givenAdapter(views) val recycler = RecyclerView(context).apply { layoutManager = LinearLayoutManager(context) @@ -1467,7 +1449,7 @@ class BlockAdapterTest { val views = listOf(title) - val adapter = buildAdapter(views) + val adapter = givenAdapter(views) val recycler = RecyclerView(context).apply { layoutManager = LinearLayoutManager(context) @@ -1606,7 +1588,7 @@ class BlockAdapterTest { val views = listOf(paragraph) - val adapter = buildAdapter(views) + val adapter = givenAdapter(views) val recycler = RecyclerView(context).apply { layoutManager = LinearLayoutManager(context) @@ -1652,7 +1634,7 @@ class BlockAdapterTest { val views = listOf(firstParagraph, secondParagraph) - val adapter = buildAdapter(views) + val adapter = givenAdapter(views) val recycler = RecyclerView(context).apply { layoutManager = LinearLayoutManager(context) @@ -1686,7 +1668,7 @@ class BlockAdapterTest { val views = listOf(paragraph) - val adapter = buildAdapter(views) + val adapter = givenAdapter(views) val recycler = RecyclerView(context).apply { layoutManager = LinearLayoutManager(context) @@ -1730,7 +1712,7 @@ class BlockAdapterTest { val views = listOf(paragraph) - val adapter = buildAdapter(views) + val adapter = givenAdapter(views) val recycler = RecyclerView(context).apply { layoutManager = LinearLayoutManager(context) @@ -1763,11 +1745,7 @@ class BlockAdapterTest { changes = listOf(READ_WRITE_MODE_CHANGED) ) ), - onSelectionChanged = { _, _ -> }, - onTextChanged = {}, clicked = {}, - onMentionEvent = {}, - onSlashEvent = {} ) assertEquals( @@ -1795,7 +1773,7 @@ class BlockAdapterTest { val views = listOf(title) - val adapter = buildAdapter(views) + val adapter = givenAdapter(views) val recycler = RecyclerView(context).apply { layoutManager = LinearLayoutManager(context) @@ -1836,7 +1814,7 @@ class BlockAdapterTest { val views = listOf(title) - val adapter = buildAdapter(views) + val adapter = givenAdapter(views) val recycler = RecyclerView(context).apply { layoutManager = LinearLayoutManager(context) @@ -1879,7 +1857,7 @@ class BlockAdapterTest { val views = listOf(title) - val adapter = buildAdapter(views) + val adapter = givenAdapter(views) val recycler = RecyclerView(context).apply { layoutManager = LinearLayoutManager(context) @@ -1951,7 +1929,7 @@ class BlockAdapterTest { val views: List = listOf(h1, h2, h3) - val adapter = buildAdapter(views) + val adapter = givenAdapter(views) val recycler = RecyclerView(context).apply { layoutManager = LinearLayoutManager(context) @@ -2064,7 +2042,7 @@ class BlockAdapterTest { h3Notselected ) - val adapter = buildAdapter(views) + val adapter = givenAdapter(views) val recycler = RecyclerView(context).apply { layoutManager = LinearLayoutManager(context) @@ -2135,7 +2113,7 @@ class BlockAdapterTest { val views: List = listOf(h1, h2, h3) - val adapter = buildAdapter(views) + val adapter = givenAdapter(views) val recycler = RecyclerView(context).apply { layoutManager = LinearLayoutManager(context) @@ -2226,7 +2204,7 @@ class BlockAdapterTest { val views: List = listOf(h1, h2, h3) - val adapter = buildAdapter(views) + val adapter = givenAdapter(views) val recycler = RecyclerView(context).apply { layoutManager = LinearLayoutManager(context) @@ -2265,11 +2243,7 @@ class BlockAdapterTest { changes = listOf(READ_WRITE_MODE_CHANGED) ) ), - onSelectionChanged = { _, _ -> }, - onTextChanged = {}, clicked = {}, - onMentionEvent = {}, - onSlashEvent = {} ) assertEquals( @@ -2301,11 +2275,7 @@ class BlockAdapterTest { changes = listOf(READ_WRITE_MODE_CHANGED) ) ), - onSelectionChanged = { _, _ -> }, - onTextChanged = {}, clicked = {}, - onMentionEvent = {}, - onSlashEvent = {} ) assertEquals( @@ -2337,11 +2307,7 @@ class BlockAdapterTest { changes = listOf(READ_WRITE_MODE_CHANGED) ) ), - onSelectionChanged = { _, _ -> }, - onTextChanged = {}, clicked = {}, - onMentionEvent = {}, - onSlashEvent = {} ) assertEquals( @@ -2369,7 +2335,7 @@ class BlockAdapterTest { val views = listOf(highlight) - val adapter = buildAdapter(views) + val adapter = givenAdapter(views) val recycler = RecyclerView(context).apply { layoutManager = LinearLayoutManager(context) @@ -2411,7 +2377,7 @@ class BlockAdapterTest { val views = listOf(highlight) - val adapter = buildAdapter(views) + val adapter = givenAdapter(views) val recycler = RecyclerView(context).apply { layoutManager = LinearLayoutManager(context) @@ -2437,11 +2403,7 @@ class BlockAdapterTest { changes = listOf(TEXT_CHANGED) ) ), - onSelectionChanged = { _, _ -> }, - onTextChanged = {}, clicked = {}, - onMentionEvent = {}, - onSlashEvent = {} ) assertEquals( @@ -2463,7 +2425,7 @@ class BlockAdapterTest { val views = listOf(highlight) - val adapter = buildAdapter(views) + val adapter = givenAdapter(views) val recycler = RecyclerView(context).apply { layoutManager = LinearLayoutManager(context) @@ -2505,7 +2467,7 @@ class BlockAdapterTest { val views = listOf(highlight) - val adapter = buildAdapter(views) + val adapter = givenAdapter(views) val recycler = RecyclerView(context).apply { layoutManager = LinearLayoutManager(context) @@ -2536,11 +2498,7 @@ class BlockAdapterTest { changes = listOf(READ_WRITE_MODE_CHANGED) ) ), - onSelectionChanged = { _, _ -> }, - onTextChanged = {}, clicked = {}, - onMentionEvent = {}, - onSlashEvent = {} ) assertEquals( @@ -2568,7 +2526,7 @@ class BlockAdapterTest { val views = listOf(bullet) - val adapter = buildAdapter(views) + val adapter = givenAdapter(views) val recycler = RecyclerView(context).apply { layoutManager = LinearLayoutManager(context) @@ -2607,7 +2565,7 @@ class BlockAdapterTest { val views = listOf(bullet) - val adapter = buildAdapter(views) + val adapter = givenAdapter(views) val recycler = RecyclerView(context).apply { layoutManager = LinearLayoutManager(context) @@ -2650,7 +2608,7 @@ class BlockAdapterTest { val views = listOf(bullet) - val adapter = buildAdapter(views) + val adapter = givenAdapter(views) val recycler = RecyclerView(context).apply { layoutManager = LinearLayoutManager(context) @@ -2681,11 +2639,7 @@ class BlockAdapterTest { changes = listOf(READ_WRITE_MODE_CHANGED) ) ), - onSelectionChanged = { _, _ -> }, - onTextChanged = {}, clicked = {}, - onMentionEvent = {}, - onSlashEvent = {} ) assertEquals( @@ -2713,7 +2667,7 @@ class BlockAdapterTest { val views = listOf(checkbox) - val adapter = buildAdapter(views) + val adapter = givenAdapter(views) val recycler = RecyclerView(context).apply { layoutManager = LinearLayoutManager(context) @@ -2752,7 +2706,7 @@ class BlockAdapterTest { val views = listOf(checkbox) - val adapter = buildAdapter(views) + val adapter = givenAdapter(views) val recycler = RecyclerView(context).apply { layoutManager = LinearLayoutManager(context) @@ -2795,7 +2749,7 @@ class BlockAdapterTest { val views = listOf(checkbox) - val adapter = buildAdapter(views) + val adapter = givenAdapter(views) val recycler = RecyclerView(context).apply { layoutManager = LinearLayoutManager(context) @@ -2826,11 +2780,7 @@ class BlockAdapterTest { changes = listOf(READ_WRITE_MODE_CHANGED) ) ), - onSelectionChanged = { _, _ -> }, - onTextChanged = {}, clicked = {}, - onMentionEvent = {}, - onSlashEvent = {} ) assertEquals( @@ -2859,7 +2809,7 @@ class BlockAdapterTest { val views = listOf(numbered) - val adapter = buildAdapter(views) + val adapter = givenAdapter(views) val recycler = RecyclerView(context).apply { layoutManager = LinearLayoutManager(context) @@ -2899,7 +2849,7 @@ class BlockAdapterTest { val views = listOf(numbered) - val adapter = buildAdapter(views) + val adapter = givenAdapter(views) val recycler = RecyclerView(context).apply { layoutManager = LinearLayoutManager(context) @@ -2943,7 +2893,7 @@ class BlockAdapterTest { val views = listOf(numbered) - val adapter = buildAdapter(views) + val adapter = givenAdapter(views) val recycler = RecyclerView(context).apply { layoutManager = LinearLayoutManager(context) @@ -2974,11 +2924,7 @@ class BlockAdapterTest { changes = listOf(READ_WRITE_MODE_CHANGED) ) ), - onSelectionChanged = { _, _ -> }, - onTextChanged = {}, clicked = {}, - onMentionEvent = {}, - onSlashEvent = {} ) assertEquals( @@ -3008,7 +2954,7 @@ class BlockAdapterTest { val views = listOf(toggle) - val adapter = buildAdapter(views) + val adapter = givenAdapter(views) val recycler = RecyclerView(context).apply { layoutManager = LinearLayoutManager(context) @@ -3049,7 +2995,7 @@ class BlockAdapterTest { val views = listOf(toggle) - val adapter = buildAdapter(views) + val adapter = givenAdapter(views) val recycler = RecyclerView(context).apply { layoutManager = LinearLayoutManager(context) @@ -3094,7 +3040,7 @@ class BlockAdapterTest { val views = listOf(toggle) - val adapter = buildAdapter(views) + val adapter = givenAdapter(views) val recycler = RecyclerView(context).apply { layoutManager = LinearLayoutManager(context) @@ -3125,11 +3071,7 @@ class BlockAdapterTest { changes = listOf(READ_WRITE_MODE_CHANGED) ) ), - onSelectionChanged = { _, _ -> }, - onTextChanged = {}, clicked = {}, - onMentionEvent = {}, - onSlashEvent = {} ) assertEquals( @@ -3173,7 +3115,7 @@ class BlockAdapterTest { ) ) - val adapter = buildAdapter(views) + val adapter = givenAdapter(views) val recycler = RecyclerView(context).apply { layoutManager = LinearLayoutManager(context) @@ -3214,7 +3156,7 @@ class BlockAdapterTest { val views = listOf(file) - val adapter = buildAdapter(views) + val adapter = givenAdapter(views) val recycler = RecyclerView(context).apply { layoutManager = LinearLayoutManager(context) @@ -3257,7 +3199,7 @@ class BlockAdapterTest { val views = listOf(file) - val adapter = buildAdapter(views) + val adapter = givenAdapter(views) val recycler = RecyclerView(context).apply { layoutManager = LinearLayoutManager(context) @@ -3296,7 +3238,7 @@ class BlockAdapterTest { val lifecycle = TestLifecycle() - val adapter = buildAdapter(listOf(givenVideo()), lifecycle = lifecycle) + val adapter = givenAdapter(listOf(givenVideo()), lifecycle = lifecycle) val holder = adapter.onCreateViewHolder(recycler, Types.HOLDER_VIDEO) @@ -3318,7 +3260,7 @@ class BlockAdapterTest { val recycler = givenRecycler() - val adapter = buildAdapter(listOf(givenVideo())) + val adapter = givenAdapter(listOf(givenVideo())) val holder = adapter.onCreateViewHolder(recycler, Types.HOLDER_VIDEO) @@ -3345,7 +3287,7 @@ class BlockAdapterTest { val recycler = givenRecycler() - val adapter = buildAdapter(listOf(givenVideo())) + val adapter = givenAdapter(listOf(givenVideo())) val holder = adapter.onCreateViewHolder(recycler, Types.HOLDER_VIDEO) @@ -3372,7 +3314,7 @@ class BlockAdapterTest { val recycler = givenRecycler() - val adapter = buildAdapter(listOf(givenVideo())) + val adapter = givenAdapter(listOf(givenVideo())) val holder = adapter.onCreateViewHolder(recycler, Types.HOLDER_VIDEO) @@ -3403,7 +3345,7 @@ class BlockAdapterTest { val runs = mutableListOf() givenPerformancePackageList().forEach { pack -> - val adapter = buildAdapter(listOf(pack.block)) + val adapter = givenAdapter(listOf(pack.block)) val holder = adapter.onCreateViewHolder(recycler, pack.holderId) check(holder.javaClass.canonicalName == pack.className) @@ -3440,7 +3382,12 @@ class BlockAdapterTest { givenPicture(), Picture::class.qualifiedName!! ), - PerformancePackage(Types.HOLDER_TITLE, "Title", givenTitle(), Document::class.qualifiedName!!) + PerformancePackage( + Types.HOLDER_TITLE, + "Title", + givenTitle(), + Document::class.qualifiedName!! + ) ) private fun givenRecycler() = RecyclerView(context).apply { @@ -3476,12 +3423,13 @@ class BlockAdapterTest { decorations = emptyList() ) - private fun buildAdapter( + private fun givenAdapter( views: List, onSplitLineEnterClicked: (String, Editable, IntRange) -> Unit = { _, _, _ -> }, onFocusChanged: (String, Boolean) -> Unit = { _, _ -> }, onTitleBlockTextChanged: (Id, String) -> Unit = { _, _ -> }, onTextChanged: (String, Editable) -> Unit = { _, _ -> }, + onToggleClicked: (String) -> Unit = {}, lifecycle: Lifecycle = TestLifecycle() ): BlockAdapter { return BlockAdapter( @@ -3498,7 +3446,7 @@ class BlockAdapterTest { onTextInputClicked = {}, onPageIconClicked = {}, onTogglePlaceholderClicked = {}, - onToggleClicked = {}, + onToggleClicked = onToggleClicked, onTextBlockTextChanged = {}, onTitleBlockTextChanged = onTitleBlockTextChanged, onTitleTextInputClicked = {}, diff --git a/core-ui/src/test/java/com/anytypeio/anytype/core_ui/HeaderBlockTest.kt b/core-ui/src/test/java/com/anytypeio/anytype/core_ui/HeaderBlockTest.kt index 998fc50373..5295d29fce 100644 --- a/core-ui/src/test/java/com/anytypeio/anytype/core_ui/HeaderBlockTest.kt +++ b/core-ui/src/test/java/com/anytypeio/anytype/core_ui/HeaderBlockTest.kt @@ -237,11 +237,7 @@ class HeaderBlockTest { ) ), item = updated, - onSelectionChanged = { _, _ -> }, - onTextChanged = {}, clicked = {}, - onMentionEvent = {}, - onSlashEvent = {} ) assertEquals( @@ -295,11 +291,7 @@ class HeaderBlockTest { ) ), item = updated, - onSelectionChanged = { _, _ -> }, - onTextChanged = {}, clicked = {}, - onMentionEvent = {}, - onSlashEvent = {} ) assertEquals( @@ -353,11 +345,7 @@ class HeaderBlockTest { ) ), item = updated, - onSelectionChanged = { _, _ -> }, - onTextChanged = {}, clicked = {}, - onMentionEvent = {}, - onSlashEvent = {} ) assertEquals( diff --git a/core-ui/src/test/java/com/anytypeio/anytype/core_ui/features/editor/BlockAdapterCheckboxTest.kt b/core-ui/src/test/java/com/anytypeio/anytype/core_ui/features/editor/BlockAdapterCheckboxTest.kt index 3588f430b9..facbcf1e08 100644 --- a/core-ui/src/test/java/com/anytypeio/anytype/core_ui/features/editor/BlockAdapterCheckboxTest.kt +++ b/core-ui/src/test/java/com/anytypeio/anytype/core_ui/features/editor/BlockAdapterCheckboxTest.kt @@ -129,49 +129,6 @@ class BlockAdapterCheckboxTest : BlockAdapterTestSetup() { ) } - @Test - fun `should not have checkboxhighlight span when turn ckeckbox from true to false`() { - - val checkbox = BlockView.Text.Checkbox( - id = MockDataFactory.randomUuid(), - text = MockDataFactory.randomString(), - isFocused = true, - isChecked = true - ) - - val views = listOf(checkbox) - - val adapter = buildAdapter(views = views) - - val recycler = RecyclerView(context).apply { - layoutManager = LinearLayoutManager(context) - } - - val holder = adapter.onCreateViewHolder(recycler, HOLDER_CHECKBOX) - - adapter.onBindViewHolder(holder, 0) - - // TESTING - - check(holder is Checkbox) - - val spans = holder.content.text!!.getSpans(0) - - assertEquals( - expected = 1, - actual = spans.size - ) - - holder.checkbox.performClick() - - val spansAfter = holder.content.text!!.getSpans(0) - - assertEquals( - expected = 0, - actual = spansAfter.size - ) - } - @Test fun `should have checkboxhighlight when payload text changed and is checked`() { @@ -209,10 +166,6 @@ class BlockAdapterCheckboxTest : BlockAdapterTestSetup() { payloads = listOf(BlockViewDiffUtil.Payload(changes = listOf(BlockViewDiffUtil.TEXT_CHANGED))), item = checkbox.copy(text = "$text Second"), clicked = {}, - onSelectionChanged = { _, _ -> }, - onTextChanged = {}, - onMentionEvent = {}, - onSlashEvent = {} ) assertEquals( @@ -266,10 +219,6 @@ class BlockAdapterCheckboxTest : BlockAdapterTestSetup() { ) ), clicked = {}, - onSelectionChanged = { _, _ -> }, - onTextChanged = {}, - onMentionEvent = {}, - onSlashEvent = {} ) assertEquals( @@ -323,10 +272,6 @@ class BlockAdapterCheckboxTest : BlockAdapterTestSetup() { ) ), clicked = {}, - onSelectionChanged = { _, _ -> }, - onTextChanged = {}, - onMentionEvent = {}, - onSlashEvent = {} ) assertEquals( @@ -372,10 +317,6 @@ class BlockAdapterCheckboxTest : BlockAdapterTestSetup() { payloads = listOf(BlockViewDiffUtil.Payload(changes = listOf(BlockViewDiffUtil.TEXT_CHANGED))), item = checkbox.copy(text = "$text Second"), clicked = {}, - onSelectionChanged = { _, _ -> }, - onTextChanged = {}, - onMentionEvent = {}, - onSlashEvent = {} ) assertEquals( @@ -420,10 +361,6 @@ class BlockAdapterCheckboxTest : BlockAdapterTestSetup() { payloads = listOf(BlockViewDiffUtil.Payload(changes = listOf(BlockViewDiffUtil.TEXT_CHANGED))), item = checkbox.copy(text = "$text Second"), clicked = {}, - onSelectionChanged = { _, _ -> }, - onTextChanged = {}, - onMentionEvent = {}, - onSlashEvent = {} ) assertEquals( diff --git a/core-ui/src/test/java/com/anytypeio/anytype/core_ui/features/editor/BlockAdapterMovementMethodTest.kt b/core-ui/src/test/java/com/anytypeio/anytype/core_ui/features/editor/BlockAdapterMovementMethodTest.kt index 17252c8bb5..4c0d3a2cd3 100644 --- a/core-ui/src/test/java/com/anytypeio/anytype/core_ui/features/editor/BlockAdapterMovementMethodTest.kt +++ b/core-ui/src/test/java/com/anytypeio/anytype/core_ui/features/editor/BlockAdapterMovementMethodTest.kt @@ -264,10 +264,6 @@ class BlockAdapterMovementMethodTest : BlockAdapterTestSetup() { ), item = updated, clicked = {}, - onSelectionChanged = { _, _ -> }, - onTextChanged = {}, - onMentionEvent = {}, - onSlashEvent = {} ) val testMM = holder.content.movementMethod @@ -338,10 +334,6 @@ class BlockAdapterMovementMethodTest : BlockAdapterTestSetup() { ), item = updated, clicked = {}, - onSelectionChanged = { _, _ -> }, - onTextChanged = {}, - onMentionEvent = {}, - onSlashEvent = {} ) val testMM = holder.content.movementMethod @@ -412,10 +404,6 @@ class BlockAdapterMovementMethodTest : BlockAdapterTestSetup() { ), item = updated, clicked = {}, - onSelectionChanged = { _, _ -> }, - onTextChanged = {}, - onMentionEvent = {}, - onSlashEvent = {} ) val testMM = holder.content.movementMethod @@ -487,10 +475,6 @@ class BlockAdapterMovementMethodTest : BlockAdapterTestSetup() { ), item = updated, clicked = {}, - onSelectionChanged = { _, _ -> }, - onTextChanged = {}, - onMentionEvent = {}, - onSlashEvent = {} ) val testMM = holder.content.movementMethod @@ -561,10 +545,6 @@ class BlockAdapterMovementMethodTest : BlockAdapterTestSetup() { ), item = updated, clicked = {}, - onSelectionChanged = { _, _ -> }, - onTextChanged = {}, - onMentionEvent = {}, - onSlashEvent = {} ) val testMM = holder.content.movementMethod @@ -636,10 +616,6 @@ class BlockAdapterMovementMethodTest : BlockAdapterTestSetup() { ), item = updated, clicked = {}, - onSelectionChanged = { _, _ -> }, - onTextChanged = {}, - onMentionEvent = {}, - onSlashEvent = {} ) val testMM = holder.content.movementMethod @@ -716,10 +692,6 @@ class BlockAdapterMovementMethodTest : BlockAdapterTestSetup() { ), item = updated, clicked = {}, - onSelectionChanged = { _, _ -> }, - onTextChanged = {}, - onMentionEvent = {}, - onSlashEvent = {} ) val testMM = holder.content.movementMethod @@ -797,10 +769,6 @@ class BlockAdapterMovementMethodTest : BlockAdapterTestSetup() { ), item = updated, clicked = {}, - onSelectionChanged = { _, _ -> }, - onTextChanged = {}, - onMentionEvent = {}, - onSlashEvent = {} ) val testMM = holder.content.movementMethod @@ -879,10 +847,6 @@ class BlockAdapterMovementMethodTest : BlockAdapterTestSetup() { ), item = updated, clicked = {}, - onSelectionChanged = { _, _ -> }, - onTextChanged = {}, - onMentionEvent = {}, - onSlashEvent = {} ) val testMM = holder.content.movementMethod @@ -949,10 +913,6 @@ class BlockAdapterMovementMethodTest : BlockAdapterTestSetup() { ), item = paragraphUpdated, clicked = {}, - onSelectionChanged = { _, _ -> }, - onTextChanged = {}, - onMentionEvent = {}, - onSlashEvent = {} ) val testMM = holder.content.movementMethod diff --git a/core-ui/src/test/java/com/anytypeio/anytype/core_ui/features/editor/BlockAdapterReadWriteModeTest.kt b/core-ui/src/test/java/com/anytypeio/anytype/core_ui/features/editor/BlockAdapterReadWriteModeTest.kt index ad3a8dc2b2..7181361ec3 100644 --- a/core-ui/src/test/java/com/anytypeio/anytype/core_ui/features/editor/BlockAdapterReadWriteModeTest.kt +++ b/core-ui/src/test/java/com/anytypeio/anytype/core_ui/features/editor/BlockAdapterReadWriteModeTest.kt @@ -18,6 +18,7 @@ import com.anytypeio.anytype.test_utils.MockDataFactory import org.junit.runner.RunWith import org.robolectric.RobolectricTestRunner import org.robolectric.annotation.Config +import kotlin.test.Ignore import kotlin.test.Test import kotlin.test.assertEquals import kotlin.test.assertFalse @@ -27,348 +28,6 @@ import kotlin.test.assertTrue @Config(sdk = [Build.VERSION_CODES.P]) @RunWith(RobolectricTestRunner::class) class BlockAdapterReadWriteModeTest : BlockAdapterTestSetup() { - - @Test - fun `endline-enter press listener should be enabled when switching from read to edit mode`() { - - // Setup - - var trigger = 0 - - val block = BlockView.Text.Paragraph( - mode = BlockView.Mode.READ, - text = MockDataFactory.randomString(), - id = MockDataFactory.randomUuid() - ) - - val views = listOf(block) - - val updated = listOf( - block.copy( - mode = BlockView.Mode.EDIT, - cursor = block.text.length, - isFocused = true - ) - ) - - val adapter = buildAdapter( - views = views, - onSplitLineEnterClicked = { _, _, _ -> trigger += 1 } - ) - - val recycler = RecyclerView(context).apply { - layoutManager = LinearLayoutManager(context) - this.adapter = adapter - } - - val holder = adapter.onCreateViewHolder(recycler, HOLDER_PARAGRAPH) - - check(holder is Paragraph) - - // Testing - - adapter.onBindViewHolder(holder, 0) - - val payloads: MutableList = mutableListOf( - BlockViewDiffUtil.Payload( - changes = listOf( - BlockViewDiffUtil.READ_WRITE_MODE_CHANGED, - BlockViewDiffUtil.FOCUS_CHANGED, - BlockViewDiffUtil.CURSOR_CHANGED - ) - ) - ) - - adapter.updateWithDiffUtil(items = updated) - - adapter.onBindViewHolder(holder, 0, payloads = payloads) - - holder.content.onEditorAction(EditorInfo.IME_ACTION_GO) - - assertEquals( - expected = 1, - actual = trigger - ) - } - - @Test - fun `split-line-enter press listener should be enabled when switching from read to edit mode`() { - - // Setup - - var trigger = 0 - - val block = BlockView.Text.Paragraph( - mode = BlockView.Mode.READ, - text = MockDataFactory.randomString(), - id = MockDataFactory.randomUuid(), - cursor = null - ) - - val views = listOf(block) - - val updated = listOf( - block.copy( - mode = BlockView.Mode.EDIT, - cursor = 5, - isFocused = true - ) - ) - - val adapter = buildAdapter( - views = views, - onSplitLineEnterClicked = { _, _, _ -> trigger += 1 } - ) - - val recycler = RecyclerView(context).apply { - layoutManager = LinearLayoutManager(context) - this.adapter = adapter - } - - val holder = adapter.onCreateViewHolder(recycler, HOLDER_PARAGRAPH) - - check(holder is Paragraph) - - // Testing - - adapter.onBindViewHolder(holder, 0) - - val payloads: MutableList = mutableListOf( - BlockViewDiffUtil.Payload( - changes = listOf( - BlockViewDiffUtil.READ_WRITE_MODE_CHANGED, - BlockViewDiffUtil.FOCUS_CHANGED, - BlockViewDiffUtil.CURSOR_CHANGED - ) - ) - ) - - adapter.updateWithDiffUtil(items = updated) - - adapter.onBindViewHolder(holder, 0, payloads = payloads) - - assertEquals( - expected = 5, - actual = holder.content.selectionStart - ) - - holder.content.onEditorAction(EditorInfo.IME_ACTION_GO) - - assertEquals( - expected = 1, - actual = trigger - ) - } - - @Test - fun `on-non-empty-block-backspace-press listener should be enabled when switching from read to edit mode`() { - - // Setup - - var trigger = 0 - - val block = BlockView.Text.Paragraph( - mode = BlockView.Mode.READ, - text = MockDataFactory.randomString(), - id = MockDataFactory.randomUuid(), - cursor = null - ) - - val views = listOf(block) - - val updated = listOf( - block.copy( - mode = BlockView.Mode.EDIT, - cursor = 0, - isFocused = true - ) - ) - - val adapter = buildAdapter( - views = views, - onNonEmptyBlockBackspaceClicked = { _, _ -> trigger += 1 } - ) - - val recycler = RecyclerView(context).apply { - layoutManager = LinearLayoutManager(context) - this.adapter = adapter - } - - val holder = adapter.onCreateViewHolder(recycler, HOLDER_PARAGRAPH) - - check(holder is Paragraph) - - // Testing - - adapter.onBindViewHolder(holder, 0) - - val payloads: MutableList = mutableListOf( - BlockViewDiffUtil.Payload( - changes = listOf( - BlockViewDiffUtil.READ_WRITE_MODE_CHANGED, - BlockViewDiffUtil.FOCUS_CHANGED, - BlockViewDiffUtil.CURSOR_CHANGED - ) - ) - ) - - adapter.updateWithDiffUtil(items = updated) - - adapter.onBindViewHolder(holder, 0, payloads = payloads) - - assertEquals( - expected = 0, - actual = holder.content.selectionStart - ) - - holder.content.dispatchKeyEvent( - KeyEvent(0, 0, KeyEvent.ACTION_DOWN, KeyEvent.KEYCODE_DEL, 0) - ) - - assertEquals( - expected = 1, - actual = trigger - ) - } - - @Test - fun `on-empty-block-backspace-press listener should be enabled when switching from read to edit mode`() { - - // Setup - - var trigger = 0 - - val block = BlockView.Text.Paragraph( - mode = BlockView.Mode.READ, - text = "", - id = MockDataFactory.randomUuid(), - cursor = null - ) - - val views = listOf(block) - - val updated = listOf( - block.copy( - mode = BlockView.Mode.EDIT, - cursor = 0, - isFocused = true - ) - ) - - val adapter = buildAdapter( - views = views, - onEmptyBlockBackspaceClicked = { trigger += 1 } - ) - - val recycler = RecyclerView(context).apply { - layoutManager = LinearLayoutManager(context) - this.adapter = adapter - } - - val holder = adapter.onCreateViewHolder(recycler, HOLDER_PARAGRAPH) - - check(holder is Paragraph) - - // Testing - - adapter.onBindViewHolder(holder, 0) - - val payloads: MutableList = mutableListOf( - BlockViewDiffUtil.Payload( - changes = listOf( - BlockViewDiffUtil.READ_WRITE_MODE_CHANGED, - BlockViewDiffUtil.FOCUS_CHANGED, - BlockViewDiffUtil.CURSOR_CHANGED - ) - ) - ) - - adapter.updateWithDiffUtil(items = updated) - - adapter.onBindViewHolder(holder, 0, payloads = payloads) - - assertEquals( - expected = 0, - actual = holder.content.selectionStart - ) - - holder.content.dispatchKeyEvent( - KeyEvent(0, 0, KeyEvent.ACTION_DOWN, KeyEvent.KEYCODE_DEL, 0) - ) - - assertEquals( - expected = 1, - actual = trigger - ) - } - - @Test - fun `checkbox-clicked listener should be enabled when switching from read to edit mode`() { - - // Setup - - var trigger = 0 - - val block = BlockView.Text.Checkbox( - mode = BlockView.Mode.READ, - text = MockDataFactory.randomString(), - id = MockDataFactory.randomUuid(), - isChecked = false - ) - - val views = listOf(block) - - val updated = listOf( - block.copy( - mode = BlockView.Mode.EDIT - ) - ) - - val adapter = buildAdapter( - views = views, - onCheckboxClicked = { trigger += 1 } - ) - - val recycler = RecyclerView(context).apply { - layoutManager = LinearLayoutManager(context) - this.adapter = adapter - } - - val holder = adapter.onCreateViewHolder(recycler, HOLDER_CHECKBOX) - - check(holder is Checkbox) - - // Testing - - adapter.onBindViewHolder(holder, 0) - - holder.checkbox.performClick() - - assertEquals( - expected = 0, - actual = trigger - ) - - val payloads: MutableList = mutableListOf( - BlockViewDiffUtil.Payload( - changes = listOf( - BlockViewDiffUtil.READ_WRITE_MODE_CHANGED - ) - ) - ) - - adapter.updateWithDiffUtil(items = updated) - - adapter.onBindViewHolder(holder, 0, payloads = payloads) - - holder.checkbox.performClick() - - assertEquals( - expected = 1, - actual = trigger - ) - } - /** * Scenario: * 1. Text block[bold, link spans] EDIT mode diff --git a/core-ui/src/test/java/com/anytypeio/anytype/core_ui/features/editor/BlockAdapterToggleTest.kt b/core-ui/src/test/java/com/anytypeio/anytype/core_ui/features/editor/BlockAdapterToggleTest.kt deleted file mode 100644 index 2440614c19..0000000000 --- a/core-ui/src/test/java/com/anytypeio/anytype/core_ui/features/editor/BlockAdapterToggleTest.kt +++ /dev/null @@ -1,91 +0,0 @@ -package com.anytypeio.anytype.core_ui.features.editor - -import android.os.Build -import androidx.recyclerview.widget.LinearLayoutManager -import androidx.recyclerview.widget.RecyclerView -import com.anytypeio.anytype.core_ui.features.editor.holders.text.Toggle -import com.anytypeio.anytype.presentation.editor.editor.model.BlockView -import com.anytypeio.anytype.presentation.editor.editor.model.types.Types.HOLDER_TOGGLE -import com.anytypeio.anytype.test_utils.MockDataFactory -import org.junit.Test -import org.junit.runner.RunWith -import org.robolectric.RobolectricTestRunner -import org.robolectric.annotation.Config -import kotlin.test.assertEquals - -@Config(sdk = [Build.VERSION_CODES.P]) -@RunWith(RobolectricTestRunner::class) -class BlockAdapterToggleTest : BlockAdapterTestSetup() { - - @Test - fun `toggle click should be intercepted when switching from read to edit mode`() { - - // Setup - - var triggerCount = 0 - - val text = MockDataFactory.randomString() - - val block = BlockView.Text.Toggle( - mode = BlockView.Mode.READ, - text = text, - id = MockDataFactory.randomUuid(), - isFocused = false - ) - - val views = listOf(block) - - val adapter = buildAdapter( - views = views, - onToggleClicked = { triggerCount = triggerCount.inc() } - ) - - val recycler = RecyclerView(context).apply { - layoutManager = LinearLayoutManager(context) - } - - val holder = adapter.onCreateViewHolder(recycler, HOLDER_TOGGLE) - - adapter.onBindViewHolder(holder, 0) - - // TESTING - - check(holder is Toggle) - - // Performing click in read-mode - - holder.toggle.performClick() - - assertEquals( - actual = triggerCount, - expected = 1 - ) - - // Updating views - - adapter.updateWithDiffUtil( - listOf( - block.copy( - mode = BlockView.Mode.EDIT - ) - ) - ) - - val payload: MutableList = mutableListOf( - BlockViewDiffUtil.Payload( - changes = listOf(BlockViewDiffUtil.READ_WRITE_MODE_CHANGED) - ) - ) - - adapter.onBindViewHolder(holder, 0, payload) - - // Performing click in edit mode - - holder.toggle.performClick() - - assertEquals( - actual = triggerCount, - expected = 2 - ) - } -} \ No newline at end of file diff --git a/core-ui/src/test/java/com/anytypeio/anytype/core_ui/uitests/BlockAdapterCheckboxTest.kt b/core-ui/src/test/java/com/anytypeio/anytype/core_ui/uitests/BlockAdapterCheckboxTest.kt new file mode 100644 index 0000000000..b30c2aed39 --- /dev/null +++ b/core-ui/src/test/java/com/anytypeio/anytype/core_ui/uitests/BlockAdapterCheckboxTest.kt @@ -0,0 +1,148 @@ +package com.anytypeio.anytype.core_ui.uitests + +import android.content.Context +import android.os.Build +import android.widget.EditText +import androidx.core.text.getSpans +import androidx.fragment.app.Fragment +import androidx.fragment.app.testing.FragmentScenario +import androidx.fragment.app.testing.launchFragmentInContainer +import androidx.recyclerview.widget.LinearLayoutManager +import androidx.recyclerview.widget.RecyclerView +import androidx.test.core.app.ApplicationProvider +import com.anytypeio.anytype.core_ui.R +import com.anytypeio.anytype.core_ui.common.CheckedCheckboxColorSpan +import com.anytypeio.anytype.presentation.editor.editor.model.BlockView +import com.anytypeio.anytype.test_utils.MockDataFactory +import com.anytypeio.anytype.test_utils.TestFragment +import com.anytypeio.anytype.test_utils.utils.onItemView +import com.anytypeio.anytype.test_utils.utils.performClick +import com.anytypeio.anytype.test_utils.utils.rVMatcher +import com.anytypeio.anytype.test_utils.utils.view_action.extractView +import org.junit.Before +import org.junit.Test +import org.junit.runner.RunWith +import org.robolectric.RobolectricTestRunner +import org.robolectric.annotation.Config +import kotlin.test.assertEquals +import com.anytypeio.anytype.test_utils.R as R_test + + +@RunWith(RobolectricTestRunner::class) +@Config( + manifest = Config.NONE, + sdk = [Build.VERSION_CODES.P], + instrumentedPackages = [ + // required to access final members on androidx.loader.content.ModernAsyncTask + "androidx.loader.content" + ] +) +class BlockAdapterCheckboxTest { + + private val context: Context = ApplicationProvider.getApplicationContext() + lateinit var scenario: FragmentScenario + + @Before + fun setUp() { + context.setTheme(R.style.Theme_MaterialComponents) + scenario = launchFragmentInContainer() + } + + @Test + fun `should not have checkbox highlight span - when turn checkbox from true to false`() { + scenario.onFragment { + + val recycler = givenRecycler(it) + + val block = givenCheckbox() + + val adapter = givenAdapter(listOf(block)) + + recycler.adapter = adapter + + R_test.id.recycler.rVMatcher().apply { + val spans = + onItemView( + 0, + R.id.checkboxContent + ).extractView().text.getSpans(0) + + assertEquals( + expected = 1, + actual = spans.size + ) + + onItemView(0, R.id.checkboxIcon).performClick() + + val spansAfter = + onItemView(0, R.id.checkboxContent).extractView().text + .getSpans(0) + + assertEquals( + expected = 0, + actual = spansAfter.size + ) + } + } + } + + @Test + fun `checkbox-clicked listener should be enabled - when switching from read to edit mode`() { + scenario.onFragment { + + var trigger = 0 + + val recycler = givenRecycler(it) + + val block = givenCheckbox(BlockView.Mode.READ) + + val adapter = givenAdapter( + views = listOf(block), + onCheckboxClicked = { trigger++ } + ) + + recycler.adapter = adapter + + R_test.id.recycler.rVMatcher().apply { + + onItemView(0, R.id.checkboxIcon).performClick() + + assertEquals( + expected = 0, + actual = trigger + ) + } + + val updated = listOf( + block.copy( + mode = BlockView.Mode.EDIT + ) + ) + + adapter.updateWithDiffUtil(items = updated) + + R_test.id.recycler.rVMatcher().apply { + + onItemView(0, R.id.checkboxIcon).performClick() + + assertEquals( + expected = 1, + actual = trigger + ) + } + } + } + + private fun givenRecycler(it: Fragment): RecyclerView = + it.view!!.findViewById(R_test.id.recycler).apply { + layoutManager = LinearLayoutManager(context) + } + + private fun givenCheckbox(mode: BlockView.Mode = BlockView.Mode.EDIT) = BlockView.Text.Checkbox( + id = MockDataFactory.randomUuid(), + text = MockDataFactory.randomString(), + isFocused = true, + isChecked = true, + mode = mode + ) +} \ No newline at end of file diff --git a/core-ui/src/test/java/com/anytypeio/anytype/core_ui/uitests/BlockAdapterReadWriteModeTest.kt b/core-ui/src/test/java/com/anytypeio/anytype/core_ui/uitests/BlockAdapterReadWriteModeTest.kt new file mode 100644 index 0000000000..96581645de --- /dev/null +++ b/core-ui/src/test/java/com/anytypeio/anytype/core_ui/uitests/BlockAdapterReadWriteModeTest.kt @@ -0,0 +1,246 @@ +package com.anytypeio.anytype.core_ui.uitests + +import android.content.Context +import android.os.Build +import android.view.KeyEvent +import android.widget.TextView +import androidx.fragment.app.Fragment +import androidx.fragment.app.testing.FragmentScenario +import androidx.fragment.app.testing.launchFragmentInContainer +import androidx.recyclerview.widget.LinearLayoutManager +import androidx.recyclerview.widget.RecyclerView +import androidx.test.core.app.ApplicationProvider +import androidx.test.espresso.action.ViewActions +import com.anytypeio.anytype.core_ui.R +import com.anytypeio.anytype.presentation.editor.editor.model.BlockView +import com.anytypeio.anytype.test_utils.MockDataFactory +import com.anytypeio.anytype.test_utils.TestFragment +import com.anytypeio.anytype.test_utils.utils.onItemView +import com.anytypeio.anytype.test_utils.utils.rVMatcher +import com.anytypeio.anytype.test_utils.utils.view_action.extractView +import org.junit.Before +import org.junit.Test +import org.junit.runner.RunWith +import org.robolectric.RobolectricTestRunner +import org.robolectric.annotation.Config +import kotlin.test.assertEquals +import com.anytypeio.anytype.test_utils.R as R_test + + +@RunWith(RobolectricTestRunner::class) +@Config( + manifest = Config.NONE, + sdk = [Build.VERSION_CODES.P], + instrumentedPackages = [ + // required to access final members on androidx.loader.content.ModernAsyncTask + "androidx.loader.content" + ] +) +class BlockAdapterReadWriteModeTest { + + private val context: Context = ApplicationProvider.getApplicationContext() + lateinit var scenario: FragmentScenario + + @Before + fun setUp() { + context.setTheme(R.style.Theme_MaterialComponents) + scenario = launchFragmentInContainer() + } + + @Test + fun `split-line-enter press listener should be enabled - when switching from read to edit mode`() { + scenario.onFragment { + + var trigger = 0 + + val recycler = givenRecycler(it) + + val block = givenParagraph() + + val adapter = givenAdapter( + views = listOf(block), + onSplitLineEnterClicked = { _, _, _ -> trigger++ } + ) + + recycler.adapter = adapter + + val updated = listOf( + block.copy( + mode = BlockView.Mode.EDIT, + cursor = 5, + isFocused = true + ) + ) + + adapter.updateWithDiffUtil(items = updated) + + R_test.id.recycler.rVMatcher().apply { + + val selectionStart = + onItemView(0, R.id.textContent).extractView().selectionStart + + assertEquals( + expected = 5, + actual = selectionStart + ) + + onItemView(0, R.id.textContent).perform(ViewActions.pressImeActionButton()) + + assertEquals( + expected = 1, + actual = trigger + ) + } + } + } + + @Test + fun `endline-enter press listener should be enabled - when switching from read to edit mode`() { + scenario.onFragment { + + var trigger = 0 + + val recycler = givenRecycler(it) + + val block = givenParagraph() + + val adapter = givenAdapter( + views = listOf(block), + onSplitLineEnterClicked = { _, _, _ -> trigger++ } + ) + + recycler.adapter = adapter + + val updated = listOf( + block.copy( + mode = BlockView.Mode.EDIT, + cursor = block.text.length, + isFocused = true + ) + ) + + adapter.updateWithDiffUtil(items = updated) + + R_test.id.recycler.rVMatcher().apply { + + onItemView(0, R.id.textContent).perform(ViewActions.pressImeActionButton()) + + assertEquals( + expected = 1, + actual = trigger + ) + } + } + } + + @Test + fun `on-non-empty-block-backspace-press listener should be enabled - when switching from read to edit mode`() { + scenario.onFragment { + + var trigger = 0 + + val recycler = givenRecycler(it) + + val block = givenParagraph() + + val adapter = givenAdapter( + views = listOf(block), + onNonEmptyBlockBackspaceClicked = { _, _ -> trigger++ } + ) + + recycler.adapter = adapter + + R_test.id.recycler.rVMatcher().apply { + + onItemView(0, R.id.textContent).perform(ViewActions.pressKey(KeyEvent.KEYCODE_DEL)) + + assertEquals( + expected = 0, + actual = trigger + ) + } + + val updated = listOf( + block.copy( + mode = BlockView.Mode.EDIT, + cursor = 0, + isFocused = true + ) + ) + + adapter.updateWithDiffUtil(items = updated) + + R_test.id.recycler.rVMatcher().apply { + + onItemView(0, R.id.textContent).perform(ViewActions.pressKey(KeyEvent.KEYCODE_DEL)) + + assertEquals( + expected = 1, + actual = trigger + ) + } + } + } + + @Test + fun `on-empty-block-backspace-press listener should be enabled - when switching from read to edit mode`() { + scenario.onFragment { + + var trigger = 0 + + val recycler = givenRecycler(it) + + val block = givenParagraph() + + val adapter = givenAdapter( + views = listOf(block), + onEmptyBlockBackspaceClicked = { trigger++ } + ) + + recycler.adapter = adapter + + R_test.id.recycler.rVMatcher().apply { + + onItemView(0, R.id.textContent).perform(ViewActions.pressKey(KeyEvent.KEYCODE_DEL)) + + assertEquals( + expected = 0, + actual = trigger + ) + } + + val updated = listOf( + block.copy( + text = "", + mode = BlockView.Mode.EDIT, + cursor = 0, + isFocused = true + ) + ) + + adapter.updateWithDiffUtil(items = updated) + + R_test.id.recycler.rVMatcher().apply { + + onItemView(0, R.id.textContent).perform(ViewActions.pressKey(KeyEvent.KEYCODE_DEL)) + + assertEquals( + expected = 1, + actual = trigger + ) + } + } + } + + private fun givenRecycler(it: Fragment): RecyclerView = + it.view!!.findViewById(R_test.id.recycler).apply { + layoutManager = LinearLayoutManager(context) + } + + private fun givenParagraph() = BlockView.Text.Paragraph( + mode = BlockView.Mode.READ, + text = MockDataFactory.randomString(), + id = MockDataFactory.randomUuid(), + cursor = null + ) +} \ No newline at end of file diff --git a/core-ui/src/test/java/com/anytypeio/anytype/core_ui/uitests/BlockAdapterShared.kt b/core-ui/src/test/java/com/anytypeio/anytype/core_ui/uitests/BlockAdapterShared.kt index d9a8c8531b..364e09c421 100644 --- a/core-ui/src/test/java/com/anytypeio/anytype/core_ui/uitests/BlockAdapterShared.kt +++ b/core-ui/src/test/java/com/anytypeio/anytype/core_ui/uitests/BlockAdapterShared.kt @@ -25,24 +25,28 @@ fun givenAdapter( onTitleCheckboxClicked: (BlockView.Title.Todo) -> Unit = {}, onTitleBlockTextChanged: (Id, String) -> Unit = { _, _ -> }, onTextChanged: (String, Editable) -> Unit = { _, _ -> }, + onToggleClicked: (String) -> Unit = {}, + onNonEmptyBlockBackspaceClicked: (String, Editable) -> Unit = { _, _ -> }, + onEmptyBlockBackspaceClicked: (String) -> Unit = {}, + onCheckboxClicked: (BlockView.Text.Checkbox) -> Unit = {}, lifecycle: Lifecycle = BlockAdapterTest.TestLifecycle(), ): BlockAdapter { return BlockAdapter( restore = LinkedList(), initialBlock = views, - onNonEmptyBlockBackspaceClicked = { _, _ -> }, - onEmptyBlockBackspaceClicked = {}, + onNonEmptyBlockBackspaceClicked = onNonEmptyBlockBackspaceClicked, + onEmptyBlockBackspaceClicked = onEmptyBlockBackspaceClicked, onSplitLineEnterClicked = onSplitLineEnterClicked, onSplitDescription = { _, _, _ -> }, onTextChanged = onTextChanged, - onCheckboxClicked = {}, + onCheckboxClicked = onCheckboxClicked, onTitleCheckboxClicked = onTitleCheckboxClicked, onFocusChanged = onFocusChanged, onSelectionChanged = { _, _ -> }, onTextInputClicked = {}, onPageIconClicked = {}, onTogglePlaceholderClicked = {}, - onToggleClicked = {}, + onToggleClicked = onToggleClicked, onTextBlockTextChanged = {}, onTitleBlockTextChanged = onTitleBlockTextChanged, onTitleTextInputClicked = {}, diff --git a/core-ui/src/test/java/com/anytypeio/anytype/core_ui/uitests/BlockAdapterToggleTest.kt b/core-ui/src/test/java/com/anytypeio/anytype/core_ui/uitests/BlockAdapterToggleTest.kt new file mode 100644 index 0000000000..6a8648a7da --- /dev/null +++ b/core-ui/src/test/java/com/anytypeio/anytype/core_ui/uitests/BlockAdapterToggleTest.kt @@ -0,0 +1,106 @@ +package com.anytypeio.anytype.core_ui.uitests + +import android.content.Context +import android.os.Build +import androidx.fragment.app.Fragment +import androidx.fragment.app.testing.FragmentScenario +import androidx.fragment.app.testing.launchFragmentInContainer +import androidx.recyclerview.widget.LinearLayoutManager +import androidx.recyclerview.widget.RecyclerView +import androidx.test.core.app.ApplicationProvider +import com.anytypeio.anytype.core_ui.R +import com.anytypeio.anytype.presentation.editor.editor.model.BlockView +import com.anytypeio.anytype.test_utils.MockDataFactory +import com.anytypeio.anytype.test_utils.TestFragment +import com.anytypeio.anytype.test_utils.utils.checkHasTextColor +import com.anytypeio.anytype.test_utils.utils.checkIsDisplayed +import com.anytypeio.anytype.test_utils.utils.onItemView +import com.anytypeio.anytype.test_utils.utils.performClick +import com.anytypeio.anytype.test_utils.utils.rVMatcher +import org.junit.Before +import org.junit.Test +import org.junit.runner.RunWith +import org.robolectric.RobolectricTestRunner +import org.robolectric.annotation.Config +import kotlin.test.assertEquals +import com.anytypeio.anytype.test_utils.R as R_test + + +@RunWith(RobolectricTestRunner::class) +@Config( + manifest = Config.NONE, + sdk = [Build.VERSION_CODES.P], + instrumentedPackages = [ + // required to access final members on androidx.loader.content.ModernAsyncTask + "androidx.loader.content" + ] +) +class BlockAdapterToggleTest { + + private val context: Context = ApplicationProvider.getApplicationContext() + lateinit var scenario: FragmentScenario + + @Before + fun setUp() { + context.setTheme(R.style.Theme_MaterialComponents) + scenario = launchFragmentInContainer() + } + + @Test + fun `should intercept toggle click - when switching from read to edit mode`() { + scenario.onFragment { + + var triggeredTimes = 0 + + val recycler = givenRecycler(it) + + val block = givenToggle() + + val adapter = givenAdapter( + views = listOf(block), + onToggleClicked = { triggeredTimes++ } + ) + + recycler.adapter = adapter + + R_test.id.recycler.rVMatcher().apply { + onItemView(0, R.id.toggle).checkIsDisplayed() + onItemView(0, R.id.toggle).performClick() + } + + assertEquals( + actual = triggeredTimes, + expected = 1 + ) + + adapter.updateWithDiffUtil( + listOf( + block.copy( + mode = BlockView.Mode.EDIT + ) + ) + ) + + R_test.id.recycler.rVMatcher().apply { + onItemView(0, R.id.toggle).performClick() + } + + assertEquals( + actual = triggeredTimes, + expected = 2 + ) + } + } + + private fun givenRecycler(it: Fragment): RecyclerView = + it.view!!.findViewById(R_test.id.recycler).apply { + layoutManager = LinearLayoutManager(context) + } + + private fun givenToggle() = BlockView.Text.Toggle( + mode = BlockView.Mode.READ, + text = MockDataFactory.randomString(), + id = MockDataFactory.randomUuid(), + isFocused = false + ) +} \ No newline at end of file diff --git a/test/android-utils/src/main/java/com/anytypeio/anytype/test_utils/utils/view_action/ExtractViewAction.kt b/test/android-utils/src/main/java/com/anytypeio/anytype/test_utils/utils/view_action/ExtractViewAction.kt new file mode 100644 index 0000000000..810c577335 --- /dev/null +++ b/test/android-utils/src/main/java/com/anytypeio/anytype/test_utils/utils/view_action/ExtractViewAction.kt @@ -0,0 +1,31 @@ +package com.anytypeio.anytype.test_utils.utils.view_action + +import android.view.View +import androidx.test.espresso.UiController +import androidx.test.espresso.ViewAction +import androidx.test.espresso.ViewInteraction +import androidx.test.espresso.matcher.ViewMatchers.isAssignableFrom +import org.hamcrest.Matcher + +class ExtractViewAction : ViewAction { + + lateinit var view: V + + override fun getConstraints(): Matcher { + return isAssignableFrom(View::class.java) + } + + override fun getDescription(): String { + return "Text of the view" + } + + override fun perform(uiController: UiController, view: View) { + this.view = view as V + } +} + +inline fun ViewInteraction.extractView(): V { + val viewAction = ExtractViewAction() + perform(viewAction) + return viewAction.view +}