diff --git a/app/src/main/java/com/anytypeio/anytype/ui/editor/EditorFragment.kt b/app/src/main/java/com/anytypeio/anytype/ui/editor/EditorFragment.kt index f5a0928efd..db4a8e7a00 100644 --- a/app/src/main/java/com/anytypeio/anytype/ui/editor/EditorFragment.kt +++ b/app/src/main/java/com/anytypeio/anytype/ui/editor/EditorFragment.kt @@ -1378,7 +1378,7 @@ open class EditorFragment : NavigationFragment(R.layout.f state.styleTextToolbar.apply { val behavior = BottomSheetBehavior.from(binding.styleToolbarMain) if (isVisible) { - binding.styleToolbarMain.setSelectedStyle(style) + binding.styleToolbarMain.setSelectedStyle(this.state) if (behavior.state == BottomSheetBehavior.STATE_HIDDEN) { keyboardDelayJobs += lifecycleScope.launch { if (binding.recycler.itemDecorationCount == 0) { @@ -1411,10 +1411,7 @@ open class EditorFragment : NavigationFragment(R.layout.f state.styleExtraToolbar.apply { if (isVisible) { - binding.styleToolbarOther.setProperties( - props = state.styleTextToolbar.props, - config = state.styleTextToolbar.config - ) + binding.styleToolbarOther.setProperties(state.styleExtraToolbar.state) BottomSheetBehavior.from(binding.styleToolbarOther).apply { setState(BottomSheetBehavior.STATE_EXPANDED) addBottomSheetCallback(onHideBottomSheetCallback) @@ -1429,12 +1426,7 @@ open class EditorFragment : NavigationFragment(R.layout.f state.styleColorBackgroundToolbar.apply { if (isVisible) { - state.styleTextToolbar.config?.let { config -> - binding.styleToolbarColors.update( - config, - state.styleTextToolbar.props - ) - } + binding.styleToolbarColors.update(state.styleColorBackgroundToolbar.state) BottomSheetBehavior.from(binding.styleToolbarColors).apply { setState(BottomSheetBehavior.STATE_EXPANDED) addBottomSheetCallback(onHideBottomSheetCallback) @@ -1448,13 +1440,29 @@ open class EditorFragment : NavigationFragment(R.layout.f } state.styleBackgroundToolbar.apply { + val behavior = BottomSheetBehavior.from(binding.styleToolbarBackground) if (isVisible) { - state.styleBackgroundToolbar.selectedBackground.let { + state.styleBackgroundToolbar.state.let { binding.styleToolbarBackground.update(it) } - BottomSheetBehavior.from(binding.styleToolbarBackground).apply { - setState(BottomSheetBehavior.STATE_EXPANDED) - addBottomSheetCallback(onHideBottomSheetCallback) + if (behavior.state == BottomSheetBehavior.STATE_HIDDEN) { + keyboardDelayJobs += lifecycleScope.launch { + if (binding.recycler.itemDecorationCount == 0) { + binding.recycler.addItemDecoration(styleToolbarFooter) + } + proceedWithHidingSoftInput() + if (insets != null) { + if (insets.isVisible(WindowInsetsCompat.Type.ime())) { + delay(DELAY_HIDE_KEYBOARD) + } + } else { + delay(DELAY_HIDE_KEYBOARD) + } + behavior.apply { + setState(BottomSheetBehavior.STATE_EXPANDED) + addBottomSheetCallback(onHideBottomSheetCallback) + } + } } } else { BottomSheetBehavior.from(binding.styleToolbarBackground).apply { diff --git a/core-models/src/main/java/com/anytypeio/anytype/core_models/ext/BlockExt.kt b/core-models/src/main/java/com/anytypeio/anytype/core_models/ext/BlockExt.kt index e851ad81e8..095dd640c0 100644 --- a/core-models/src/main/java/com/anytypeio/anytype/core_models/ext/BlockExt.kt +++ b/core-models/src/main/java/com/anytypeio/anytype/core_models/ext/BlockExt.kt @@ -276,4 +276,9 @@ fun List.getChildrenIdsList(parent: Id): List { fun List.isAllTextAndNoneCodeBlocks(): Boolean = all { block -> block.content is Content.Text && block.content.style != Content.Text.Style.CODE_SNIPPET + } + +fun List.isAllTextBlocks(): Boolean = + all { block -> + block.content is Content.Text } \ No newline at end of file diff --git a/core-ui/src/main/java/com/anytypeio/anytype/core_ui/features/editor/holders/other/Code.kt b/core-ui/src/main/java/com/anytypeio/anytype/core_ui/features/editor/holders/other/Code.kt index ff60528e6f..5d698f508b 100644 --- a/core-ui/src/main/java/com/anytypeio/anytype/core_ui/features/editor/holders/other/Code.kt +++ b/core-ui/src/main/java/com/anytypeio/anytype/core_ui/features/editor/holders/other/Code.kt @@ -71,6 +71,7 @@ class Code(val binding: ItemBlockCodeSnippetBinding) : BlockViewHolder(binding.r setBackgroundColor(item.backgroundColor) + setCursor(item) setFocus(item) content.addTextChangedListener( @@ -158,6 +159,10 @@ class Code(val binding: ItemBlockCodeSnippetBinding) : BlockViewHolder(binding.r setFocus(item) } + if (payload.isCursorChanged) { + setCursor(item = item) + } + if (payload.backgroundColorChanged()) { setBackgroundColor(item.backgroundColor) } @@ -196,6 +201,18 @@ class Code(val binding: ItemBlockCodeSnippetBinding) : BlockViewHolder(binding.r } } + private fun setCursor(item: BlockView.Code) { + if (item.isFocused) { + Timber.d("Setting cursor: $item") + item.cursor?.let { + val length = content.text?.length ?: 0 + if (it in 0..length) { + content.setSelection(it) + } + } + } + } + private fun setBackgroundColor(color: String? = null) { Timber.d("Setting background color: $color") val value = ThemeColor.values().find { value -> value.title == color } diff --git a/core-ui/src/main/java/com/anytypeio/anytype/core_ui/widgets/StyleToolbarMainWidget.kt b/core-ui/src/main/java/com/anytypeio/anytype/core_ui/widgets/StyleToolbarMainWidget.kt index 34020e13fd..e692464c8a 100644 --- a/core-ui/src/main/java/com/anytypeio/anytype/core_ui/widgets/StyleToolbarMainWidget.kt +++ b/core-ui/src/main/java/com/anytypeio/anytype/core_ui/widgets/StyleToolbarMainWidget.kt @@ -12,6 +12,7 @@ import com.anytypeio.anytype.core_ui.databinding.WidgetStyleToolbarMainBinding import com.anytypeio.anytype.core_ui.extensions.toast import com.anytypeio.anytype.core_ui.reactive.clicks import com.anytypeio.anytype.presentation.editor.editor.model.UiBlock +import com.anytypeio.anytype.presentation.editor.editor.styling.StyleToolbarState import kotlinx.coroutines.flow.map import kotlinx.coroutines.flow.merge @@ -48,8 +49,8 @@ class StyleToolbarMainWidget @JvmOverloads constructor( val other = binding.dots.clicks() val colors = binding.markupColors.clicks() - fun setSelectedStyle(style: TextStyle?) { - when (style) { + fun setSelectedStyle(state: StyleToolbarState.Text?) { + when (state?.textStyle) { TextStyle.P -> select(binding.tvStyleText.id) TextStyle.H1 -> select(binding.tvStyleTitle.id) TextStyle.H2 -> select(binding.tvStyleHeading.id) diff --git a/core-ui/src/main/java/com/anytypeio/anytype/core_ui/widgets/toolbar/StyleToolbarExtraWidget.kt b/core-ui/src/main/java/com/anytypeio/anytype/core_ui/widgets/toolbar/StyleToolbarExtraWidget.kt index 1a70d11f71..e1c34b2c9b 100644 --- a/core-ui/src/main/java/com/anytypeio/anytype/core_ui/widgets/toolbar/StyleToolbarExtraWidget.kt +++ b/core-ui/src/main/java/com/anytypeio/anytype/core_ui/widgets/toolbar/StyleToolbarExtraWidget.kt @@ -6,10 +6,7 @@ import android.view.LayoutInflater import androidx.cardview.widget.CardView import com.anytypeio.anytype.core_ui.databinding.WidgetBlockStyleExtraBinding import com.anytypeio.anytype.core_ui.reactive.clicks -import com.anytypeio.anytype.presentation.editor.editor.Markup -import com.anytypeio.anytype.presentation.editor.editor.control.ControlPanelState -import com.anytypeio.anytype.presentation.editor.editor.model.Alignment -import com.anytypeio.anytype.presentation.editor.editor.styling.StyleConfig +import com.anytypeio.anytype.presentation.editor.editor.styling.StyleToolbarState import com.anytypeio.anytype.presentation.editor.editor.styling.StylingEvent import kotlinx.coroutines.flow.Flow import kotlinx.coroutines.flow.map @@ -36,36 +33,31 @@ class StyleToolbarExtraWidget @JvmOverloads constructor( ) fun setProperties( - props: ControlPanelState.Toolbar.Styling.Props?, - config: StyleConfig? + state: StyleToolbarState.Other ) = with(binding) { - bold.isSelected = props?.isBold ?: false - italic.isSelected = props?.isItalic ?: false - strikethrough.isSelected = props?.isStrikethrough ?: false - code.isSelected = props?.isCode ?: false - alignmentLeft.isSelected = props?.alignment == Alignment.START - alignmentMiddle.isSelected = props?.alignment == Alignment.CENTER - alignmentRight.isSelected = props?.alignment == Alignment.END - setUrl.isSelected = props?.isLinked ?: false + bold.isSelected = state.isBoldSelected + italic.isSelected = state.isItalicSelected + strikethrough.isSelected = state.isStrikethroughSelected + code.isSelected = state.isCodeSelected + alignmentLeft.isSelected = state.isAlignStartSelected + alignmentMiddle.isSelected = state.isAlignCenterSelected + alignmentRight.isSelected = state.isAlignEndSelected - config?.let { - alignmentLeft.isEnabled = it.enabledAlignment.contains(Alignment.START) - alignmentLeftIcon.isEnabled = alignmentLeft.isEnabled - alignmentRight.isEnabled = it.enabledAlignment.contains(Alignment.END) - alignmentRightIcon.isEnabled = alignmentRight.isEnabled - alignmentMiddle.isEnabled = it.enabledAlignment.contains(Alignment.CENTER) - alignmentMiddleIcon.isEnabled = alignmentMiddle.isEnabled - - bold.isEnabled = it.enabledMarkup.contains(Markup.Type.BOLD) - boldIcon.isEnabled = bold.isEnabled - italic.isEnabled = it.enabledMarkup.contains(Markup.Type.ITALIC) - italicIcon.isEnabled = italic.isEnabled - strikethrough.isEnabled = it.enabledMarkup.contains(Markup.Type.STRIKETHROUGH) - strikethroughIcon.isEnabled = strikethrough.isEnabled - code.isEnabled = it.enabledMarkup.contains(Markup.Type.KEYBOARD) - codeIcon.isEnabled = code.isEnabled - setUrl.isEnabled = it.enabledMarkup.contains(Markup.Type.LINK) - setUrlIcon.isEnabled = setUrl.isEnabled - } + alignmentLeft.isEnabled = state.isSupportAlignStart + alignmentLeftIcon.isEnabled = alignmentLeft.isEnabled + alignmentRight.isEnabled = state.isSupportAlignEnd + alignmentRightIcon.isEnabled = alignmentRight.isEnabled + alignmentMiddle.isEnabled = state.isSupportAlignCenter + alignmentMiddleIcon.isEnabled = alignmentMiddle.isEnabled + bold.isEnabled = state.isSupportBold + boldIcon.isEnabled = bold.isEnabled + italic.isEnabled = state.isSupportItalic + italicIcon.isEnabled = italic.isEnabled + strikethrough.isEnabled = state.isSupportStrikethrough + strikethroughIcon.isEnabled = strikethrough.isEnabled + code.isEnabled = state.isSupportCode + codeIcon.isEnabled = code.isEnabled + setUrl.isEnabled = state.isSupportLinked + setUrlIcon.isEnabled = setUrl.isEnabled } } \ No newline at end of file diff --git a/core-ui/src/main/java/com/anytypeio/anytype/core_ui/widgets/toolbar/style/StyleAdapter.kt b/core-ui/src/main/java/com/anytypeio/anytype/core_ui/widgets/toolbar/style/StyleAdapter.kt index d1718b0514..3380bccbe4 100644 --- a/core-ui/src/main/java/com/anytypeio/anytype/core_ui/widgets/toolbar/style/StyleAdapter.kt +++ b/core-ui/src/main/java/com/anytypeio/anytype/core_ui/widgets/toolbar/style/StyleAdapter.kt @@ -5,30 +5,17 @@ import android.view.ViewGroup import androidx.recyclerview.widget.RecyclerView import com.anytypeio.anytype.core_ui.databinding.BlockStyleToolbarBackgroundBinding import com.anytypeio.anytype.core_ui.databinding.BlockStyleToolbarColorBinding -import com.anytypeio.anytype.presentation.editor.editor.Markup -import com.anytypeio.anytype.presentation.editor.editor.control.ControlPanelState -import com.anytypeio.anytype.presentation.editor.editor.model.Alignment -import com.anytypeio.anytype.presentation.editor.editor.styling.StyleConfig +import com.anytypeio.anytype.presentation.editor.editor.styling.StyleToolbarState import com.anytypeio.anytype.presentation.editor.editor.styling.StylingEvent -import com.anytypeio.anytype.presentation.editor.editor.styling.StylingType class StyleAdapter( - var props: ControlPanelState.Toolbar.Styling.Props?, - private val visibleTypes: ArrayList, - private val enabledMarkup: ArrayList, - private val enabledAlignment: ArrayList, + private var state: StyleToolbarState.ColorBackground, private val onStylingEvent: (StylingEvent) -> Unit ) : RecyclerView.Adapter() { - @Deprecated("Maybe legacy, maybe not.") - fun updateConfig(config: StyleConfig, props: ControlPanelState.Toolbar.Styling.Props?) { - visibleTypes.clear() - visibleTypes.addAll(config.visibleTypes) - enabledMarkup.clear() - enabledMarkup.addAll(config.enabledMarkup) - enabledAlignment.clear() - enabledAlignment.addAll(config.enabledAlignment) - this.props = props + fun update(state: StyleToolbarState.ColorBackground) { + this.state = state + notifyDataSetChanged() } override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): RecyclerView.ViewHolder { @@ -51,10 +38,10 @@ class StyleAdapter( override fun onBindViewHolder(holder: RecyclerView.ViewHolder, position: Int) { when (holder) { is StyleTextColorViewHolder -> { - holder.bind(onStylingEvent, props?.color) + holder.bind(onStylingEvent, state.color) } is StyleBackgroundViewHolder -> { - holder.bind(onStylingEvent, props?.background) + holder.bind(onStylingEvent, state.background) } } } diff --git a/core-ui/src/main/java/com/anytypeio/anytype/core_ui/widgets/toolbar/style/StyleBackgroundToolbarWidget.kt b/core-ui/src/main/java/com/anytypeio/anytype/core_ui/widgets/toolbar/style/StyleBackgroundToolbarWidget.kt index d28fcafc6b..5627ae484e 100644 --- a/core-ui/src/main/java/com/anytypeio/anytype/core_ui/widgets/toolbar/style/StyleBackgroundToolbarWidget.kt +++ b/core-ui/src/main/java/com/anytypeio/anytype/core_ui/widgets/toolbar/style/StyleBackgroundToolbarWidget.kt @@ -7,6 +7,7 @@ import androidx.cardview.widget.CardView import com.anytypeio.anytype.core_ui.databinding.WidgetBlockStyleToolbarBackgroundBinding import com.anytypeio.anytype.core_ui.reactive.clicks import com.anytypeio.anytype.presentation.editor.editor.ThemeColor +import com.anytypeio.anytype.presentation.editor.editor.styling.StyleToolbarState import com.anytypeio.anytype.presentation.editor.editor.styling.StylingEvent import kotlinx.coroutines.flow.Flow import kotlinx.coroutines.flow.map @@ -46,19 +47,19 @@ class StyleBackgroundToolbarWidget @JvmOverloads constructor( .map { StylingEvent.Coloring.Background(ThemeColor.GREEN) } ) - fun update(background: String?) { + fun update(state: StyleToolbarState.Background) { with(binding.flowColors) { - backgroundColorDefault.isSelected = background == ThemeColor.DEFAULT.title - backgroundColorGrey.isSelected = background == ThemeColor.GREY.title - backgroundColorYellow.isSelected = background == ThemeColor.YELLOW.title - backgroundColorOrange.isSelected = background == ThemeColor.ORANGE.title - backgroundColorRed.isSelected = background == ThemeColor.RED.title - backgroundColorPink.isSelected = background == ThemeColor.PINK.title - backgroundColorPurple.isSelected = background == ThemeColor.PURPLE.title - backgroundColorBlue.isSelected = background == ThemeColor.BLUE.title - backgroundColorIce.isSelected = background == ThemeColor.ICE.title - backgroundColorTeal.isSelected = background == ThemeColor.TEAL.title - backgroundColorGreen.isSelected = background == ThemeColor.GREEN.title + backgroundColorDefault.isSelected = state.background == ThemeColor.DEFAULT.title + backgroundColorGrey.isSelected = state.background == ThemeColor.GREY.title + backgroundColorYellow.isSelected = state.background == ThemeColor.YELLOW.title + backgroundColorOrange.isSelected = state.background == ThemeColor.ORANGE.title + backgroundColorRed.isSelected = state.background == ThemeColor.RED.title + backgroundColorPink.isSelected = state.background == ThemeColor.PINK.title + backgroundColorPurple.isSelected = state.background == ThemeColor.PURPLE.title + backgroundColorBlue.isSelected = state.background == ThemeColor.BLUE.title + backgroundColorIce.isSelected = state.background == ThemeColor.ICE.title + backgroundColorTeal.isSelected = state.background == ThemeColor.TEAL.title + backgroundColorGreen.isSelected = state.background == ThemeColor.GREEN.title } } } \ No newline at end of file diff --git a/core-ui/src/main/java/com/anytypeio/anytype/core_ui/widgets/toolbar/style/StyleColorToolbarWidget.kt b/core-ui/src/main/java/com/anytypeio/anytype/core_ui/widgets/toolbar/style/StyleColorToolbarWidget.kt index 6146241679..b342d1cbf2 100644 --- a/core-ui/src/main/java/com/anytypeio/anytype/core_ui/widgets/toolbar/style/StyleColorToolbarWidget.kt +++ b/core-ui/src/main/java/com/anytypeio/anytype/core_ui/widgets/toolbar/style/StyleColorToolbarWidget.kt @@ -7,8 +7,7 @@ import android.widget.TextView import androidx.cardview.widget.CardView import com.anytypeio.anytype.core_ui.R import com.anytypeio.anytype.core_ui.databinding.WidgetBlockStyleToolbarColorsBinding -import com.anytypeio.anytype.presentation.editor.editor.control.ControlPanelState -import com.anytypeio.anytype.presentation.editor.editor.styling.StyleConfig +import com.anytypeio.anytype.presentation.editor.editor.styling.StyleToolbarState import com.anytypeio.anytype.presentation.editor.editor.styling.StylingEvent import com.google.android.material.tabs.TabLayoutMediator import kotlinx.coroutines.channels.Channel @@ -23,10 +22,7 @@ class StyleColorToolbarWidget @JvmOverloads constructor( private val channel = Channel() private val blockStyleAdapter = StyleAdapter( - props = null, - visibleTypes = arrayListOf(), - enabledAlignment = arrayListOf(), - enabledMarkup = arrayListOf() + state = StyleToolbarState.ColorBackground.empty() ) { event -> Timber.d("Styling Event : $event") channel.trySend(event) @@ -56,8 +52,7 @@ class StyleColorToolbarWidget @JvmOverloads constructor( }.attach() } - fun update(config: StyleConfig, props: ControlPanelState.Toolbar.Styling.Props?) { - blockStyleAdapter.updateConfig(config, props) - blockStyleAdapter.notifyDataSetChanged() + fun update(state: StyleToolbarState.ColorBackground) { + blockStyleAdapter.update(state) } } \ No newline at end of file diff --git a/presentation/src/main/java/com/anytypeio/anytype/presentation/editor/ControlPanelMachine.kt b/presentation/src/main/java/com/anytypeio/anytype/presentation/editor/ControlPanelMachine.kt index ec285242a5..76907e58eb 100644 --- a/presentation/src/main/java/com/anytypeio/anytype/presentation/editor/ControlPanelMachine.kt +++ b/presentation/src/main/java/com/anytypeio/anytype/presentation/editor/ControlPanelMachine.kt @@ -2,24 +2,16 @@ package com.anytypeio.anytype.presentation.editor import com.anytypeio.anytype.core_models.Block import com.anytypeio.anytype.core_models.TextBlock -import com.anytypeio.anytype.core_models.TextStyle -import com.anytypeio.anytype.core_models.ext.overlap import com.anytypeio.anytype.core_models.misc.Overlap -import com.anytypeio.anytype.domain.misc.UrlBuilder import com.anytypeio.anytype.presentation.common.StateReducer import com.anytypeio.anytype.presentation.editor.ControlPanelMachine.* -import com.anytypeio.anytype.presentation.editor.editor.Markup -import com.anytypeio.anytype.presentation.editor.editor.ThemeColor import com.anytypeio.anytype.presentation.editor.editor.control.ControlPanelState import com.anytypeio.anytype.presentation.editor.editor.control.ControlPanelState.Companion.init import com.anytypeio.anytype.presentation.editor.editor.control.ControlPanelState.Toolbar -import com.anytypeio.anytype.presentation.editor.editor.model.Alignment import com.anytypeio.anytype.presentation.editor.editor.slash.SlashWidgetState -import com.anytypeio.anytype.presentation.editor.editor.styling.StyleConfig -import com.anytypeio.anytype.presentation.editor.editor.styling.getStyleConfig +import com.anytypeio.anytype.presentation.editor.editor.styling.StyleToolbarState import com.anytypeio.anytype.presentation.editor.editor.styling.getSupportedMarkupTypes import com.anytypeio.anytype.presentation.extension.* -import com.anytypeio.anytype.presentation.mapper.marks import com.anytypeio.anytype.presentation.navigation.DefaultObjectView import com.anytypeio.anytype.presentation.objects.ObjectTypeView import kotlinx.coroutines.CoroutineScope @@ -96,12 +88,6 @@ sealed class ControlPanelMachine { object OnBlockStyleSelected : Event() - /** - * Represents an event when user selected block background color on [Toolbar.Styling] toolbar. - */ - object OnBlockBackgroundColorSelected : Event() - - /** * Represents an event when user cleares the current focus by closing keyboard. */ @@ -122,23 +108,6 @@ sealed class ControlPanelMachine { val style: Block.Content.Text.Style ) : Event() - data class OnBlockActionToolbarStyleClicked( - val target: Block, - val focused: Boolean, - val selection: IntRange?, - val urlBuilder: UrlBuilder, - val details: Block.Details - ) : Event() - - data class OnMultiSelectTextStyleClicked( - val target: Toolbar.Styling.Target?, - val config: StyleConfig?, - val props: Toolbar.Styling.Props?, - val style: TextStyle? - ) : Event() - - data class OnMultiSelectBackgroundStyleClicked(val selectedBackground: String?) : Event() - sealed class SearchToolbar : Event() { object OnEnterSearchMode : SearchToolbar() object OnExitSearchMode : SearchToolbar() @@ -155,8 +124,14 @@ sealed class ControlPanelMachine { */ sealed class StylingToolbar : Event() { - object OnExtraClicked : StylingToolbar() - object OnColorBackgroundClicked : StylingToolbar() + data class OnUpdateTextToolbar(val state: StyleToolbarState.Text) : StylingToolbar() + data class OnUpdateBackgroundToolbar(val state: StyleToolbarState.Background) : + StylingToolbar() + + data class OnUpdateColorBackgroundToolbar(val state: StyleToolbarState.ColorBackground) : + StylingToolbar() + + data class OnUpdateOtherToolbar(val state: StyleToolbarState.Other) : StylingToolbar() object OnExtraClosed : StylingToolbar() object OnColorBackgroundClosed : StylingToolbar() data class OnClose(val focused: Boolean) : StylingToolbar() @@ -222,19 +197,7 @@ sealed class ControlPanelMachine { } sealed class OnRefresh : Event() { - data class StyleToolbar( - val target: Block?, - val selection: IntRange?, - val urlBuilder: UrlBuilder, - val details: Block.Details - ) : OnRefresh() data class Markup(val target: Block?, val selection: IntRange?) : OnRefresh() - data class StyleToolbarMulti( - val target: Toolbar.Styling.Target?, - val config: StyleConfig?, - val props: Toolbar.Styling.Props?, - val style: TextStyle? - ) : OnRefresh() } object OnDocumentMenuClicked : Event() @@ -394,7 +357,6 @@ sealed class ControlPanelMachine { } is Event.OnMarkupTextColorSelected -> state.copy() is Event.OnBlockTextColorSelected -> state.copy() - is Event.OnBlockBackgroundColorSelected -> state.copy() is Event.OnBlockStyleSelected -> state.copy() is Event.OnAddBlockToolbarOptionSelected -> state.copy() is Event.OnMarkupBackgroundColorSelected -> state.copy() @@ -417,78 +379,6 @@ sealed class ControlPanelMachine { ) } } - is Event.OnBlockActionToolbarStyleClicked -> { - val target = target( - block = event.target, - details = event.details, - urlBuilder = event.urlBuilder - ) - val style = event.target.let { - val content = it.content - check(content is Block.Content.Text) - content.style - } - state.copy( - mainToolbar = state.mainToolbar.copy( - isVisible = false - ), - styleTextToolbar = state.styleTextToolbar.copy( - isVisible = true, - target = target, - style = style, - config = event.target.getStyleConfig(event.focused, event.selection), - props = getPropsForSelection(target, event.selection) - ), - navigationToolbar = state.navigationToolbar.copy( - isVisible = false - ), - styleBackgroundToolbar = Toolbar.Styling.Background.reset() - ) - } - // TODO move it somewhere in appropriate group - is Event.OnMultiSelectTextStyleClicked -> { - state.copy( - mainToolbar = state.mainToolbar.copy( - isVisible = false - ), - styleTextToolbar = state.styleTextToolbar.copy( - isVisible = true, - target = event.target, - style = event.style, - props = event.props, - config = event.config - ), - navigationToolbar = state.navigationToolbar.copy( - isVisible = false - ), - objectTypesToolbar = Toolbar.ObjectTypes.reset(), - styleBackgroundToolbar = Toolbar.Styling.Background.reset() - ) - } - is Event.OnMultiSelectBackgroundStyleClicked -> { - state.copy( - mainToolbar = state.mainToolbar.copy( - isVisible = false - ), - styleTextToolbar = state.styleTextToolbar.copy( - isVisible = false - ), - navigationToolbar = state.navigationToolbar.copy( - isVisible = false - ), - objectTypesToolbar = Toolbar.ObjectTypes.reset(), - styleColorBackgroundToolbar = Toolbar.Styling.ColorBackground( - isVisible = false - ), - styleBackgroundToolbar = Toolbar.Styling.Background( - isVisible = true, - selectedBackground = event.selectedBackground - ) - ) - } - is Event.OnRefresh.StyleToolbar -> { - handleRefreshForMarkupLevelStyling(state, event) - } is Event.OnRefresh.Markup -> { if (event.target != null && event.selection != null) { state.copy( @@ -500,16 +390,6 @@ sealed class ControlPanelMachine { state.copy() } } - is Event.OnRefresh.StyleToolbarMulti -> { - state.copy( - styleTextToolbar = state.styleTextToolbar.copy( - props = event.props, - style = event.style, - target = event.target, - config = event.config - ) - ) - } is Event.MultiSelect -> { handleMultiSelectEvent(event, state) } @@ -604,120 +484,26 @@ sealed class ControlPanelMachine { } } - private fun handleRefreshForMarkupLevelStyling( - state: ControlPanelState, - event: Event.OnRefresh.StyleToolbar - ): ControlPanelState { - val target = - event.target?.let { - target( - block = it, - urlBuilder = event.urlBuilder, - details = event.details - ) - } - val style = event.target?.let { - val content = it.content - check(content is Block.Content.Text) - content.style - } ?: TextStyle.P - return state.copy( - styleTextToolbar = state.styleTextToolbar.copy( - target = target, - props = target?.let { - Toolbar.Styling.Props( - isBold = it.isBold, - isItalic = it.isItalic, - isStrikethrough = it.isStrikethrough, - isCode = it.isCode, - isLinked = it.isLinked, - color = it.color, - background = it.background, - alignment = it.alignment - ) - }, - style = style - ) - ) - } - - private fun getPropsForSelection(target: Toolbar.Styling.Target, selection: IntRange?) - : Toolbar.Styling.Props { - return if (selection != null && selection.first != selection.last) { - getMarkupLevelStylingProps(target, selection) - } else { - Toolbar.Styling.Props( - isBold = target.isBold, - isItalic = target.isItalic, - isStrikethrough = target.isStrikethrough, - isCode = target.isCode, - isLinked = target.isLinked, - color = target.color, - background = target.background, - alignment = target.alignment - ) - } - } - - private fun getMarkupLevelStylingProps( - target: Toolbar.Styling.Target, - selection: IntRange - ): Toolbar.Styling.Props { - - var color: String? = null - var background: String? = null - - val colorOverlaps = mutableListOf() - val backgroundOverlaps = mutableListOf() - - target.marks.forEach { mark -> - if (mark is Markup.Mark.TextColor) { - val range = mark.from..mark.to - val overlap = selection.overlap(range) - if (incl.contains(overlap)) - color = mark.color - else - colorOverlaps.add(overlap) - } else if (mark is Markup.Mark.BackgroundColor) { - val range = mark.from..mark.to - val overlap = selection.overlap(range) - if (incl.contains(overlap)) - background = mark.background - else - backgroundOverlaps.add(overlap) - } - } - - if (color == null) { - if (colorOverlaps.isEmpty() || colorOverlaps.none { value -> excl.contains(value) }) - color = target.color ?: ThemeColor.DEFAULT.title - } - - if (background == null) { - if (backgroundOverlaps.isEmpty() || backgroundOverlaps.none { value -> - excl.contains( - value - ) - }) - background = target.background ?: ThemeColor.DEFAULT.title - } - - return Toolbar.Styling.Props( - isBold = target.marks.isBoldInRange(selection), - isItalic = target.marks.isItalicInRange(selection), - isStrikethrough = target.marks.isStrikethroughInRange(selection), - isCode = target.marks.isKeyboardInRange(selection), - isLinked = target.marks.isLinkInRange(selection), - color = color, - background = background, - alignment = target.alignment - ) - } - private fun handleStylingToolbarEvent( event: Event.StylingToolbar, state: ControlPanelState ): ControlPanelState = when (event) { + is Event.StylingToolbar.OnUpdateTextToolbar -> { + state.copy( + mainToolbar = state.mainToolbar.copy( + isVisible = false + ), + styleTextToolbar = state.styleTextToolbar.copy( + isVisible = true, + state = event.state + ), + navigationToolbar = state.navigationToolbar.copy( + isVisible = false + ), + objectTypesToolbar = Toolbar.ObjectTypes.reset(), + styleBackgroundToolbar = Toolbar.Styling.Background.reset() + ) + } is Event.StylingToolbar.OnClose -> { if (event.focused) { state.copy( @@ -756,21 +542,10 @@ sealed class ControlPanelMachine { styleBackgroundToolbar = Toolbar.Styling.Background.reset() ) } - is Event.StylingToolbar.OnExtraClicked -> { + is Event.StylingToolbar.OnUpdateOtherToolbar -> { state.copy( - styleTextToolbar = state.styleTextToolbar.copy( - isVisible = false - ), - styleExtraToolbar = Toolbar.Styling.Extra(true), - styleBackgroundToolbar = Toolbar.Styling.Background.reset() - ) - } - is Event.StylingToolbar.OnColorBackgroundClicked -> { - state.copy( - styleTextToolbar = state.styleTextToolbar.copy( - isVisible = false - ), - styleColorBackgroundToolbar = Toolbar.Styling.ColorBackground(true), + styleTextToolbar = Toolbar.Styling.reset(), + styleExtraToolbar = Toolbar.Styling.Extra(true, event.state), styleBackgroundToolbar = Toolbar.Styling.Background.reset() ) } @@ -779,7 +554,7 @@ sealed class ControlPanelMachine { styleTextToolbar = state.styleTextToolbar.copy( isVisible = true ), - styleExtraToolbar = Toolbar.Styling.Extra(false), + styleExtraToolbar = Toolbar.Styling.Extra.reset(), styleBackgroundToolbar = Toolbar.Styling.Background.reset() ) } @@ -788,7 +563,7 @@ sealed class ControlPanelMachine { styleTextToolbar = state.styleTextToolbar.copy( isVisible = true ), - styleColorBackgroundToolbar = Toolbar.Styling.ColorBackground(false), + styleColorBackgroundToolbar = Toolbar.Styling.ColorBackground.reset(), styleBackgroundToolbar = Toolbar.Styling.Background.reset() ) } @@ -797,6 +572,34 @@ sealed class ControlPanelMachine { styleBackgroundToolbar = Toolbar.Styling.Background.reset() ) } + is Event.StylingToolbar.OnUpdateBackgroundToolbar -> { + state.copy( + mainToolbar = state.mainToolbar.copy( + isVisible = false + ), + styleTextToolbar = Toolbar.Styling.reset(), + navigationToolbar = state.navigationToolbar.copy( + isVisible = false + ), + objectTypesToolbar = Toolbar.ObjectTypes.reset(), + styleColorBackgroundToolbar = Toolbar.Styling.ColorBackground.reset(), + styleBackgroundToolbar = Toolbar.Styling.Background( + isVisible = true, + state = event.state + ) + ) + } + is Event.StylingToolbar.OnUpdateColorBackgroundToolbar -> { + state.copy( + styleColorBackgroundToolbar = Toolbar.Styling.ColorBackground( + isVisible = true, + state = event.state + ), + styleTextToolbar = Toolbar.Styling.reset(), + styleBackgroundToolbar = Toolbar.Styling.Background.reset(), + styleExtraToolbar = Toolbar.Styling.Extra.reset() + ) + } } private fun handleMentionEvent( @@ -1050,44 +853,6 @@ sealed class ControlPanelMachine { } } - //todo Need refactoring - private fun target( - block: Block, - details: Block.Details, - urlBuilder: UrlBuilder - ): Toolbar.Styling.Target = - when (val content = block.content) { - is Block.Content.RelationBlock -> { - Toolbar.Styling.Target( - id = block.id, - text = "", - color = null, - background = block.backgroundColor, - alignment = null, - marks = listOf() - ) - } - is Block.Content.Text -> { - Toolbar.Styling.Target( - id = block.id, - text = content.text, - color = content.color, - background = block.backgroundColor, - alignment = content.align?.let { alignment -> - when (alignment) { - Block.Align.AlignCenter -> Alignment.CENTER - Block.Align.AlignLeft -> Alignment.START - Block.Align.AlignRight -> Alignment.END - } - }, - marks = content.marks(urlBuilder = urlBuilder, details = details) - ) - } - else -> { - throw IllegalArgumentException("Unexpected content type for style toolbar: ${block.content::class.java.simpleName}") - } - } - private fun logState(text: String, state: ControlPanelState) { Timber.i( "REDUCER, $text STATE:${ diff --git a/presentation/src/main/java/com/anytypeio/anytype/presentation/editor/EditorViewModel.kt b/presentation/src/main/java/com/anytypeio/anytype/presentation/editor/EditorViewModel.kt index 2ed1e2d68f..12a36d5cfe 100644 --- a/presentation/src/main/java/com/anytypeio/anytype/presentation/editor/EditorViewModel.kt +++ b/presentation/src/main/java/com/anytypeio/anytype/presentation/editor/EditorViewModel.kt @@ -30,6 +30,7 @@ import com.anytypeio.anytype.core_models.ext.content import com.anytypeio.anytype.core_models.ext.descendants import com.anytypeio.anytype.core_models.ext.getFirstLinkOrObjectMarkupParam import com.anytypeio.anytype.core_models.ext.isAllTextAndNoneCodeBlocks +import com.anytypeio.anytype.core_models.ext.isAllTextBlocks import com.anytypeio.anytype.core_models.ext.parents import com.anytypeio.anytype.core_models.ext.process import com.anytypeio.anytype.core_models.ext.sortByType @@ -113,7 +114,6 @@ import com.anytypeio.anytype.presentation.editor.editor.mention.MentionConst.MEN import com.anytypeio.anytype.presentation.editor.editor.mention.MentionConst.MENTION_TITLE_EMPTY import com.anytypeio.anytype.presentation.editor.editor.mention.MentionEvent import com.anytypeio.anytype.presentation.editor.editor.mention.getMentionName -import com.anytypeio.anytype.presentation.editor.editor.model.Alignment import com.anytypeio.anytype.presentation.editor.editor.model.BlockView import com.anytypeio.anytype.presentation.editor.editor.model.Focusable import com.anytypeio.anytype.presentation.editor.editor.model.UiBlock @@ -133,8 +133,13 @@ import com.anytypeio.anytype.presentation.editor.editor.slash.SlashWidgetState import com.anytypeio.anytype.presentation.editor.editor.slash.convertToMarkType import com.anytypeio.anytype.presentation.editor.editor.slash.convertToUiBlock import com.anytypeio.anytype.presentation.editor.editor.slash.toSlashItemView -import com.anytypeio.anytype.presentation.editor.editor.styling.StyleConfig import com.anytypeio.anytype.presentation.editor.editor.styling.StylingEvent +import com.anytypeio.anytype.presentation.editor.editor.styling.getIds +import com.anytypeio.anytype.presentation.editor.editor.styling.getStyleBackgroundToolbarState +import com.anytypeio.anytype.presentation.editor.editor.styling.getStyleColorBackgroundToolbarState +import com.anytypeio.anytype.presentation.editor.editor.styling.getStyleOtherToolbarState +import com.anytypeio.anytype.presentation.editor.editor.styling.getStyleTextToolbarState +import com.anytypeio.anytype.presentation.editor.editor.toCoreModel import com.anytypeio.anytype.presentation.editor.editor.updateText import com.anytypeio.anytype.presentation.editor.model.EditorFooter import com.anytypeio.anytype.presentation.editor.model.TextUpdate @@ -163,9 +168,6 @@ import com.anytypeio.anytype.presentation.extension.sendAnalyticsSetDescriptionE import com.anytypeio.anytype.presentation.extension.sendAnalyticsSetTitleEvent import com.anytypeio.anytype.presentation.extension.sendAnalyticsUpdateTextMarkupEvent import com.anytypeio.anytype.presentation.extension.sendAnalyticsWritingEvent -import com.anytypeio.anytype.presentation.mapper.getPropsForSelectedTextBlocks -import com.anytypeio.anytype.presentation.mapper.getSelectedBackgroundForSelectedBlocks -import com.anytypeio.anytype.presentation.mapper.getTextStyleForSelectedTextBlocks import com.anytypeio.anytype.presentation.mapper.mark import com.anytypeio.anytype.presentation.mapper.style import com.anytypeio.anytype.presentation.mapper.toObjectTypeView @@ -690,47 +692,15 @@ class EditorViewModel( private fun refreshStyleToolbar(document: Document) { controlPanelViewState.value?.let { state -> - if (state.styleTextToolbar.isVisible || state.styleColorBackgroundToolbar.isVisible) { - when (mode) { - is EditorMode.Styling.Multi -> { - val ids = (mode as EditorMode.Styling.Multi).targets - val selected = blocks.filter { ids.contains(it.id) } - controlPanelInteractor.onEvent( - event = ControlPanelMachine.Event.OnRefresh.StyleToolbarMulti( - target = null, - config = StyleConfig.emptyState(), - props = selected.getPropsForSelectedTextBlocks(), - style = selected.getTextStyleForSelectedTextBlocks() - ) - ) - } - is EditorMode.Styling.Single -> { - state.styleTextToolbar.target?.id?.let { targetId -> - controlPanelInteractor.onEvent( - event = ControlPanelMachine.Event.OnRefresh.StyleToolbar( - target = document.find { it.id == targetId }, - selection = orchestrator.stores.textSelection.current().selection, - urlBuilder = urlBuilder, - details = orchestrator.stores.details.current() - ) - ) - } - } - else -> { - Timber.e("refreshStyleToolbar, wrong mode:$mode, skip refresh") - } - } + if (state.styleTextToolbar.isVisible) { + val ids = mode.getIds() + if (ids.isNullOrEmpty()) return + onSendRefreshStyleTextToolbarEvent(ids) } if (state.styleBackgroundToolbar.isVisible) { - if (mode is EditorMode.Styling.Multi) { - val ids = (mode as EditorMode.Styling.Multi).targets - val selected = blocks.filter { ids.contains(it.id) } - controlPanelInteractor.onEvent( - ControlPanelMachine.Event.OnMultiSelectBackgroundStyleClicked( - selectedBackground = selected.getSelectedBackgroundForSelectedBlocks() - ) - ) - } + val ids = mode.getIds() + if (ids.isNullOrEmpty()) return + onSendRefreshStyleBackgroundToolbarEvent(ids) } if (state.markupMainToolbar.isVisible) { controlPanelInteractor.onEvent( @@ -740,9 +710,54 @@ class EditorViewModel( ) ) } + if (state.styleColorBackgroundToolbar.isVisible) { + val ids = mode.getIds() + if (ids.isNullOrEmpty()) return + onSendUpdateStyleColorBackgroundToolbarEvent(ids) + } + if (state.styleExtraToolbar.isVisible) { + val ids = mode.getIds() + if (ids.isNullOrEmpty()) return + onSendUpdateStyleOtherToolbarEvent(ids) + } } } + private fun onSendRefreshStyleTextToolbarEvent(ids: List) { + val selected = blocks.filter { ids.contains(it.id) } + val isAllSelectedText = selected.isAllTextBlocks() + if (isAllSelectedText) { + val state = selected.map { it.content.asText() }.getStyleTextToolbarState() + controlPanelInteractor.onEvent( + ControlPanelMachine.Event.StylingToolbar.OnUpdateTextToolbar(state) + ) + } + } + + private fun onSendRefreshStyleBackgroundToolbarEvent(ids: List) { + val selected = blocks.filter { ids.contains(it.id) } + val state = selected.getStyleBackgroundToolbarState() + controlPanelInteractor.onEvent( + ControlPanelMachine.Event.StylingToolbar.OnUpdateBackgroundToolbar(state) + ) + } + + private fun onSendUpdateStyleColorBackgroundToolbarEvent(ids: List) { + val selected = blocks.filter { ids.contains(it.id) } + val state = selected.getStyleColorBackgroundToolbarState() + controlPanelInteractor.onEvent( + ControlPanelMachine.Event.StylingToolbar.OnUpdateColorBackgroundToolbar(state) + ) + } + + private fun onSendUpdateStyleOtherToolbarEvent(ids: List) { + val selected = blocks.filter { ids.contains(it.id) } + val state = selected.map { it.content.asText() }.getStyleOtherToolbarState() + controlPanelInteractor.onEvent( + ControlPanelMachine.Event.StylingToolbar.OnUpdateOtherToolbar(state) + ) + } + private fun dispatchToUI(views: List) { stateData.postValue( ViewState.Success( @@ -1625,148 +1640,47 @@ class EditorViewModel( fun onStylingToolbarEvent(event: StylingEvent) { Timber.d("onStylingToolbarEvent, event:[$event]") - val state = controlPanelViewState.value!! + val ids: List? = mode.getIds() + if (ids.isNullOrEmpty()) return when (event) { is StylingEvent.Coloring.Text -> { - val currentMode = mode - if (currentMode is EditorMode.Styling.Multi) { - onToolbarTextColorAction(currentMode.targets.toList(), event.color.title) - } else { - proceedWithStylingEvent(state, Markup.Type.TEXT_COLOR, event.color.title) - } - viewModelScope.sendAnalyticsUpdateTextMarkupEvent( - analytics = analytics, - type = Content.Text.Mark.Type.TEXT_COLOR, - context = analyticsContext - ) + onToolbarTextColorAction(ids, event.color.title) } is StylingEvent.Coloring.Background -> { - val currentMode = mode - if (currentMode is EditorMode.Styling.Multi) { - onBlockBackgroundColorAction(currentMode.targets.toList(), event.color.title) - viewModelScope.sendAnalyticsBlockBackgroundEvent( - analytics = analytics, - count = currentMode.targets.size, - color = event.color.title, - context = analyticsContext - ) - } else { - proceedWithStylingEvent(state, Markup.Type.BACKGROUND_COLOR, event.color.title) - viewModelScope.sendAnalyticsBlockBackgroundEvent( - analytics = analytics, - count = 1, - color = event.color.title, - context = analyticsContext - ) - } + onBlockBackgroundColorAction(ids, event.color.title) } is StylingEvent.Markup.Bold -> { - val currentMode = mode - if (currentMode is EditorMode.Styling.Multi) { - sendToast(ERROR_UNSUPPORTED_BEHAVIOR) - } else { - proceedWithStylingEvent(state, Markup.Type.BOLD, null) - } - viewModelScope.sendAnalyticsUpdateTextMarkupEvent( - analytics = analytics, - type = Content.Text.Mark.Type.BOLD, - context = analyticsContext - ) + onUpdateBlockListMarkup(ids, Markup.Type.BOLD) } is StylingEvent.Markup.Italic -> { - val currentMode = mode - if (currentMode is EditorMode.Styling.Multi) { - sendToast(ERROR_UNSUPPORTED_BEHAVIOR) - } else { - proceedWithStylingEvent(state, Markup.Type.ITALIC, null) - } - viewModelScope.sendAnalyticsUpdateTextMarkupEvent( - analytics = analytics, - type = Content.Text.Mark.Type.ITALIC, - context = analyticsContext - ) + onUpdateBlockListMarkup(ids, Markup.Type.ITALIC) } is StylingEvent.Markup.StrikeThrough -> { - val currentMode = mode - if (currentMode is EditorMode.Styling.Multi) { - sendToast(ERROR_UNSUPPORTED_BEHAVIOR) - } else { - proceedWithStylingEvent(state, Markup.Type.STRIKETHROUGH, null) - } + onUpdateBlockListMarkup(ids, Markup.Type.STRIKETHROUGH) } is StylingEvent.Markup.Code -> { - val currentMode = mode - if (currentMode is EditorMode.Styling.Multi) { - sendToast(ERROR_UNSUPPORTED_BEHAVIOR) - } else { - proceedWithStylingEvent(state, Markup.Type.KEYBOARD, null) - } + onUpdateBlockListMarkup(ids, Markup.Type.KEYBOARD) } is StylingEvent.Markup.Link -> { - val currentMode = mode - if (currentMode is EditorMode.Styling.Multi) { - sendToast(ERROR_UNSUPPORTED_BEHAVIOR) + if (ids.size == 1) { + onBlockStyleLinkClicked(ids[0]) } else { - proceedWithStylingEvent(state, Markup.Type.LINK, null) + sendToast(ERROR_UNSUPPORTED_BEHAVIOR) } } is StylingEvent.Alignment.Left -> { - val currentMode = mode - if (currentMode is EditorMode.Styling.Multi) { - proceedWithAlignmentUpdate( - targets = currentMode.targets.toList(), - alignment = Block.Align.AlignLeft - ) - } else { - onBlockAlignmentActionClicked(Alignment.START) - } + proceedWithAlignmentUpdate(ids, Block.Align.AlignLeft) } is StylingEvent.Alignment.Center -> { - val currentMode = mode - if (currentMode is EditorMode.Styling.Multi) { - proceedWithAlignmentUpdate( - targets = currentMode.targets.toList(), - alignment = Block.Align.AlignCenter - ) - } else { - onBlockAlignmentActionClicked(Alignment.CENTER) - } + proceedWithAlignmentUpdate(ids, Block.Align.AlignCenter) } is StylingEvent.Alignment.Right -> { - val currentMode = mode - if (currentMode is EditorMode.Styling.Multi) { - proceedWithAlignmentUpdate( - targets = currentMode.targets.toList(), - alignment = Block.Align.AlignRight - ) - } else { - onBlockAlignmentActionClicked(Alignment.END) - } + proceedWithAlignmentUpdate(ids, Block.Align.AlignRight) } else -> Timber.d("Ignoring styling toolbar event: $event") } } - private fun proceedWithStylingEvent( - state: ControlPanelState, - type: Markup.Type, - param: String? - ) { - state.styleTextToolbar.target?.id?.let { id -> - when (type) { - Markup.Type.ITALIC -> onBlockStyleMarkupActionClicked(id, type) - Markup.Type.BOLD -> onBlockStyleMarkupActionClicked(id, type) - Markup.Type.STRIKETHROUGH -> onBlockStyleMarkupActionClicked(id, type) - Markup.Type.TEXT_COLOR -> onToolbarTextColorAction(listOf(id), param) - Markup.Type.BACKGROUND_COLOR -> onBlockBackgroundColorAction(listOf(id), param) - Markup.Type.LINK -> onBlockStyleLinkClicked(id) - Markup.Type.KEYBOARD -> onBlockStyleMarkupActionClicked(id, type) - Markup.Type.MENTION -> Unit - Markup.Type.OBJECT -> Unit - } - } ?: run { Timber.e("Target id was missing for markup styling event: $type") } - } - fun onStyleToolbarMarkupAction(type: Markup.Type, param: String? = null) { Timber.d("onStyleToolbarMarkupAction, type:[$type] param:[$param]") viewModelScope.launch { @@ -1784,19 +1698,6 @@ class EditorViewModel( ) } - private fun onBlockAlignmentActionClicked(alignment: Alignment) { - controlPanelViewState.value?.styleTextToolbar?.target?.id?.let { id -> - proceedWithAlignmentUpdate( - targets = listOf(id), - alignment = when (alignment) { - Alignment.START -> Block.Align.AlignLeft - Alignment.CENTER -> Block.Align.AlignCenter - Alignment.END -> Block.Align.AlignRight - } - ) - } - } - private fun proceedWithAlignmentUpdate(targets: List, alignment: Block.Align) { viewModelScope.launch { orchestrator.proxies.intents.send( @@ -1828,20 +1729,29 @@ class EditorViewModel( ) ) } + viewModelScope.sendAnalyticsUpdateTextMarkupEvent( + analytics = analytics, + type = Content.Text.Mark.Type.TEXT_COLOR, + context = analyticsContext + ) } - private fun onBlockBackgroundColorAction(targets: List, color: String?) { - check(color != null) - controlPanelInteractor.onEvent(ControlPanelMachine.Event.OnBlockBackgroundColorSelected) + private fun onBlockBackgroundColorAction(ids: List, color: String) { viewModelScope.launch { orchestrator.proxies.intents.send( Intent.Text.UpdateBackgroundColor( context = context, - targets = targets, + targets = ids, color = color ) ) } + viewModelScope.sendAnalyticsBlockBackgroundEvent( + analytics = analytics, + count = ids.size, + color = color, + context = analyticsContext + ) } private fun onBlockStyleLinkClicked(id: String) { @@ -1853,44 +1763,23 @@ class EditorViewModel( stateData.value = ViewState.OpenLinkScreen(context, target, range) } - private fun onBlockStyleMarkupActionClicked(id: String, action: Markup.Type) { - - controlPanelInteractor.onEvent( - ControlPanelMachine.Event.OnBlockStyleSelected - ) - - val target = blocks.first { it.id == id } - val content = target.content as Content.Text - - if (content.text.isNotEmpty()) { - - val new = target.markup( - type = action, - range = 0..content.text.length, - param = null - ) - - val update = blocks.map { block -> - if (block.id != target.id) - block - else - new - } - - orchestrator.stores.document.update(update) - - viewModelScope.launch { refresh() } - - viewModelScope.launch { - proceedWithUpdatingText( - intent = Intent.Text.UpdateText( - context = context, - target = new.id, - text = new.content().text, - marks = new.content().marks + private fun onUpdateBlockListMarkup(ids: List, type: Markup.Type) { + viewModelScope.launch { + orchestrator.proxies.intents.send( + Intent.Text.UpdateMark( + context = context, + targets = ids, + mark = Content.Text.Mark( + range = IntRange(0, Int.MAX_VALUE), + type = type.toCoreModel() ) ) - } + ) + sendAnalyticsUpdateTextMarkupEvent( + analytics = analytics, + type = type, + context = analyticsContext + ) } } @@ -2310,7 +2199,8 @@ class EditorViewModel( private fun proceedWithStyleToolbarEvent() { val target = orchestrator.stores.focus.current().id val targetBlock = blocks.find { it.id == target } - if (targetBlock != null) { + val isText = targetBlock?.content is Content.Text + if (targetBlock != null && isText) { mode = EditorMode.Styling.Single( target = target, cursor = orchestrator.stores.textSelection.current().selection?.first @@ -2321,41 +2211,37 @@ class EditorViewModel( renderCommand.send(Unit) } - val textSelection = orchestrator.stores.textSelection.current() - - controlPanelInteractor.onEvent( - ControlPanelMachine.Event.OnBlockActionToolbarStyleClicked( - target = targetBlock, - focused = textSelection.isNotEmpty, - selection = textSelection.selection, - urlBuilder = urlBuilder, - details = orchestrator.stores.details.current() + if ((targetBlock.content as Content.Text).style == Content.Text.Style.CODE_SNIPPET) { + val state = listOf(targetBlock).getStyleBackgroundToolbarState() + controlPanelInteractor.onEvent( + ControlPanelMachine.Event.StylingToolbar.OnUpdateBackgroundToolbar(state) ) - ) + } else { + val styleState = + listOf(targetBlock).map { it.content.asText() }.getStyleTextToolbarState() + controlPanelInteractor.onEvent( + ControlPanelMachine.Event.StylingToolbar.OnUpdateTextToolbar(styleState) + ) + } } else { Timber.e("Target block for style menu not found. Target id: $target") - sendToast("Target block for style menu not found.") + sendToast("Couldn't show style menu") } } private fun proceedWithMultiStyleToolbarEvent() { val selected = blocks.filter { currentSelection().contains(it.id) } - val isAllSelectedText = selected.isAllTextAndNoneCodeBlocks() + val isAllTextAndNoneCodeBlocks = selected.isAllTextAndNoneCodeBlocks() mode = EditorMode.Styling.Multi(currentSelection()) - if (isAllSelectedText) { + if (isAllTextAndNoneCodeBlocks) { + val styleState = selected.map { it.content.asText() }.getStyleTextToolbarState() controlPanelInteractor.onEvent( - ControlPanelMachine.Event.OnMultiSelectTextStyleClicked( - target = null, - config = StyleConfig.emptyState(), - props = selected.getPropsForSelectedTextBlocks(), - style = selected.getTextStyleForSelectedTextBlocks() - ) + ControlPanelMachine.Event.StylingToolbar.OnUpdateTextToolbar(styleState) ) } else { + val styleState = selected.getStyleBackgroundToolbarState() controlPanelInteractor.onEvent( - ControlPanelMachine.Event.OnMultiSelectBackgroundStyleClicked( - selectedBackground = selected.getSelectedBackgroundForSelectedBlocks() - ) + ControlPanelMachine.Event.StylingToolbar.OnUpdateBackgroundToolbar(styleState) ) } } @@ -2448,9 +2334,7 @@ class EditorViewModel( fun onCloseBlockStyleBackgroundToolbarClicked() { Timber.d("onCloseBlockStyleColorToolbarClicked, ") - controlPanelInteractor.onEvent( - ControlPanelMachine.Event.StylingToolbar.OnBackgroundClosed - ) + onCloseBlockStyleToolbarClicked() } fun onBlockToolbarBlockActionsClicked() { @@ -2527,30 +2411,27 @@ class EditorViewModel( fun onUpdateTextBlockStyle(uiBlock: UiBlock) { Timber.d("onUpdateSingleTextBlockStyle, uiBlock:[$uiBlock]") - (mode as? EditorMode.Styling.Single)?.let { eMode -> - proceedUpdateBlockStyle( - targets = listOf(eMode.target), - uiBlock = uiBlock, - errorAction = { sendToast("Cannot convert block to $uiBlock") } - ) - } - (mode as? EditorMode.Styling.Multi)?.let { - proceedUpdateBlockStyle( - targets = currentSelection().toList(), - uiBlock = uiBlock, - errorAction = { sendToast("Cannot convert block to $uiBlock") } - ) - } + val ids = mode.getIds() + if (ids.isNullOrEmpty()) return + proceedUpdateBlockStyle( + targets = ids, + uiBlock = uiBlock, + errorAction = { sendToast("Cannot convert block to $uiBlock") } + ) } fun onBlockStyleToolbarOtherClicked() { Timber.d("onBlockStyleToolbarOtherClicked, ") - controlPanelInteractor.onEvent(ControlPanelMachine.Event.StylingToolbar.OnExtraClicked) + val ids = mode.getIds() + if (ids.isNullOrEmpty()) return + onSendUpdateStyleOtherToolbarEvent(ids) } fun onBlockStyleToolbarColorClicked() { Timber.d("onBlockStyleToolbarColorClicked, ") - controlPanelInteractor.onEvent(ControlPanelMachine.Event.StylingToolbar.OnColorBackgroundClicked) + val ids = mode.getIds() + if (ids.isNullOrEmpty()) return + onSendUpdateStyleColorBackgroundToolbarEvent(ids) } private fun proceedUpdateBlockStyle( diff --git a/presentation/src/main/java/com/anytypeio/anytype/presentation/editor/editor/Transformation.kt b/presentation/src/main/java/com/anytypeio/anytype/presentation/editor/editor/Transformation.kt index 9df33d9703..eaa0d76bc8 100644 --- a/presentation/src/main/java/com/anytypeio/anytype/presentation/editor/editor/Transformation.kt +++ b/presentation/src/main/java/com/anytypeio/anytype/presentation/editor/editor/Transformation.kt @@ -29,23 +29,25 @@ fun Block.markup( val new = Mark( range = range, - type = when (type) { - Markup.Type.BOLD -> Mark.Type.BOLD - Markup.Type.ITALIC -> Mark.Type.ITALIC - Markup.Type.STRIKETHROUGH -> Mark.Type.STRIKETHROUGH - Markup.Type.TEXT_COLOR -> Mark.Type.TEXT_COLOR - Markup.Type.LINK -> Mark.Type.LINK - Markup.Type.BACKGROUND_COLOR -> Mark.Type.BACKGROUND_COLOR - Markup.Type.KEYBOARD -> Mark.Type.KEYBOARD - Markup.Type.MENTION -> Mark.Type.MENTION - Markup.Type.OBJECT -> Mark.Type.OBJECT - }, + type =type.toCoreModel(), param = param ) return copy(content = content.addMarkToContent(new)) } +fun Markup.Type.toCoreModel(): Mark.Type = when (this) { + Markup.Type.BOLD -> Mark.Type.BOLD + Markup.Type.ITALIC -> Mark.Type.ITALIC + Markup.Type.STRIKETHROUGH -> Mark.Type.STRIKETHROUGH + Markup.Type.TEXT_COLOR -> Mark.Type.TEXT_COLOR + Markup.Type.LINK -> Mark.Type.LINK + Markup.Type.BACKGROUND_COLOR -> Mark.Type.BACKGROUND_COLOR + Markup.Type.KEYBOARD -> Mark.Type.KEYBOARD + Markup.Type.MENTION -> Mark.Type.MENTION + Markup.Type.OBJECT -> Mark.Type.OBJECT +} + fun Block.Content.Text.addMarkToContent(mark: Mark): Block.Content.Text { return if (mark.isClickableMark()) { this.copy(marks = marks.addClickableMark(mark).sortByType()) diff --git a/presentation/src/main/java/com/anytypeio/anytype/presentation/editor/editor/control/ControlPanelState.kt b/presentation/src/main/java/com/anytypeio/anytype/presentation/editor/editor/control/ControlPanelState.kt index 06070397bf..1bdebfcbf9 100644 --- a/presentation/src/main/java/com/anytypeio/anytype/presentation/editor/editor/control/ControlPanelState.kt +++ b/presentation/src/main/java/com/anytypeio/anytype/presentation/editor/editor/control/ControlPanelState.kt @@ -1,10 +1,8 @@ package com.anytypeio.anytype.presentation.editor.editor.control -import com.anytypeio.anytype.core_models.TextStyle import com.anytypeio.anytype.presentation.editor.editor.Markup -import com.anytypeio.anytype.presentation.editor.editor.model.Alignment import com.anytypeio.anytype.presentation.editor.editor.slash.SlashWidgetState -import com.anytypeio.anytype.presentation.editor.editor.styling.StyleConfig +import com.anytypeio.anytype.presentation.editor.editor.styling.StyleToolbarState import com.anytypeio.anytype.presentation.editor.markup.MarkupStyleDescriptor import com.anytypeio.anytype.presentation.navigation.DefaultObjectView import com.anytypeio.anytype.presentation.objects.ObjectTypeView @@ -103,85 +101,47 @@ data class ControlPanelState( */ data class Styling( override val isVisible: Boolean, - val target: Target? = null, - val config: StyleConfig? = null, - val props: Props? = null, - val style: TextStyle? = TextStyle.P + val state: StyleToolbarState.Text ) : Toolbar() { companion object { fun reset() = Styling( isVisible = false, - target = null, - props = null, + state = StyleToolbarState.Text.empty() ) } - data class Extra(override val isVisible: Boolean) : Toolbar() { + data class Extra( + override val isVisible: Boolean, + val state: StyleToolbarState.Other + ) : Toolbar() { companion object { - fun reset() = Extra(false) + fun reset() = Extra( + isVisible = false, + state = StyleToolbarState.Other.empty() + ) } } - data class ColorBackground(override val isVisible: Boolean = false) : Toolbar() { + data class ColorBackground( + override val isVisible: Boolean = false, + val state: StyleToolbarState.ColorBackground + ) : Toolbar() { companion object { - fun reset() = ColorBackground(false) + fun reset() = ColorBackground( + isVisible = false, + state = StyleToolbarState.ColorBackground.empty() + ) } } data class Background( override val isVisible: Boolean, - val selectedBackground: String? + val state: StyleToolbarState.Background ) : Toolbar() { companion object { - fun reset() = Background(isVisible = false, selectedBackground = null) - } - } - - /** - * Target's properties corresponding to current selection or styling mode. - */ - data class Props( - val isBold: Boolean = false, - val isItalic: Boolean = false, - val isStrikethrough: Boolean = false, - val isCode: Boolean = false, - val isLinked: Boolean = false, - val color: String? = null, - val background: String? = null, - val alignment: Alignment? = null - ) - - /** - * Target block associated with this toolbar. - */ - data class Target( - val id: String, - val text: String, - val color: String?, - val background: String?, - val alignment: Alignment?, - val marks: List - ) { - - val isBold: Boolean = marks.any { mark -> - mark is Markup.Mark.Bold && mark.from == 0 && mark.to == text.length - } - - val isItalic: Boolean = marks.any { mark -> - mark is Markup.Mark.Italic && mark.from == 0 && mark.to == text.length - } - - val isStrikethrough: Boolean = marks.any { mark -> - mark is Markup.Mark.Strikethrough && mark.from == 0 && mark.to == text.length - } - - val isCode: Boolean = marks.any { mark -> - mark is Markup.Mark.Keyboard && mark.from == 0 && mark.to == text.length - } - - val isLinked: Boolean = marks.any { mark -> - mark is Markup.Mark.Link && mark.from == 0 && mark.to == text.length + fun reset() = + Background(isVisible = false, state = StyleToolbarState.Background.empty()) } } } @@ -312,7 +272,8 @@ data class ControlPanelState( count = 0 ), styleTextToolbar = Toolbar.Styling( - isVisible = false + isVisible = false, + state = StyleToolbarState.Text.empty() ), mentionToolbar = Toolbar.MentionToolbar( isVisible = false, diff --git a/presentation/src/main/java/com/anytypeio/anytype/presentation/editor/editor/ext/BlockViewExt.kt b/presentation/src/main/java/com/anytypeio/anytype/presentation/editor/editor/ext/BlockViewExt.kt index b1bd56c001..d79b9e22af 100644 --- a/presentation/src/main/java/com/anytypeio/anytype/presentation/editor/editor/ext/BlockViewExt.kt +++ b/presentation/src/main/java/com/anytypeio/anytype/presentation/editor/editor/ext/BlockViewExt.kt @@ -387,7 +387,12 @@ fun List.updateCursorAndEditMode( isFocused = isTarget, cursor = if (isTarget) cursor else null ) - is BlockView.Code -> view.copy(mode = BlockView.Mode.EDIT, isSelected = false) + is BlockView.Code -> view.copy( + mode = BlockView.Mode.EDIT, + isSelected = false, + isFocused = isTarget, + cursor = if (isTarget) cursor else null + ) is BlockView.Error.File -> view.copy(mode = BlockView.Mode.EDIT, isSelected = false) is BlockView.Error.Video -> view.copy(mode = BlockView.Mode.EDIT, isSelected = false) is BlockView.Error.Picture -> view.copy(mode = BlockView.Mode.EDIT, isSelected = false) diff --git a/presentation/src/main/java/com/anytypeio/anytype/presentation/editor/editor/model/BlockView.kt b/presentation/src/main/java/com/anytypeio/anytype/presentation/editor/editor/model/BlockView.kt index 73586668a4..c635661312 100644 --- a/presentation/src/main/java/com/anytypeio/anytype/presentation/editor/editor/model/BlockView.kt +++ b/presentation/src/main/java/com/anytypeio/anytype/presentation/editor/editor/model/BlockView.kt @@ -580,10 +580,11 @@ sealed class BlockView : ViewType { override var isFocused: Boolean = false, override val isSelected: Boolean = false, override val color: String? = null, + override var cursor: Int? = null, override val backgroundColor: String? = null, override val indent: Int = 0, val lang: String? = null - ) : BlockView(), Permission, Selectable, Focusable, Indentable, TextSupport { + ) : BlockView(), Permission, Selectable, Focusable, Cursor, Indentable, TextSupport { override fun getViewType() = HOLDER_CODE_SNIPPET } diff --git a/presentation/src/main/java/com/anytypeio/anytype/presentation/editor/editor/styling/StyleConfig.kt b/presentation/src/main/java/com/anytypeio/anytype/presentation/editor/editor/styling/StyleConfig.kt deleted file mode 100644 index afd1fc87ca..0000000000 --- a/presentation/src/main/java/com/anytypeio/anytype/presentation/editor/editor/styling/StyleConfig.kt +++ /dev/null @@ -1,345 +0,0 @@ -package com.anytypeio.anytype.presentation.editor.editor.styling - -import com.anytypeio.anytype.core_models.Block -import com.anytypeio.anytype.presentation.editor.editor.Markup -import com.anytypeio.anytype.presentation.editor.editor.model.Alignment - -data class StyleConfig( - val visibleTypes: List, - val enabledMarkup: List, - val enabledAlignment: List -) { - - companion object { - fun emptyState() = StyleConfig( - visibleTypes = emptyList(), - enabledMarkup = emptyList(), - enabledAlignment = emptyList() - ) - } -} - -fun Block.getStyleConfig(focus: Boolean?, selection: IntRange?): StyleConfig = - when (val cnt = content) { - is Block.Content.Text -> cnt.getTextStyleConfig(focus, selection) - is Block.Content.Link -> cnt.getLinkStyleConfig() - is Block.Content.File -> cnt.getFileStyleConfig(focus) - is Block.Content.Bookmark -> cnt.getBookmarkStyleConfig(focus) - is Block.Content.RelationBlock -> cnt.getRelationStyleConfig() - else -> StyleConfig.emptyState() - } - -fun Block.Content.Bookmark.getBookmarkStyleConfig(focus: Boolean?): StyleConfig { - check(focus == null) { "Bookmark block should has null focus" } - return getStyleConfig() -} - -fun Block.Content.Bookmark.getStyleConfig(): StyleConfig = StyleConfig.emptyState() - -fun Block.Content.Link.getLinkStyleConfig(): StyleConfig = StyleConfig( - visibleTypes = listOf(StylingType.BACKGROUND), - enabledMarkup = emptyList(), - enabledAlignment = emptyList() -) - -fun Block.Content.RelationBlock.getRelationStyleConfig(): StyleConfig = StyleConfig( - visibleTypes = listOf(StylingType.BACKGROUND), - enabledMarkup = emptyList(), - enabledAlignment = emptyList() -) - -fun Block.Content.File.getFileStyleConfig(focus: Boolean?): StyleConfig { - check(focus == null) { "File block should has null focus" } - return getStyleConfig() -} - -fun Block.Content.File.getStyleConfig(): StyleConfig = when (type) { - Block.Content.File.Type.FILE -> { - StyleConfig( - visibleTypes = listOf(StylingType.BACKGROUND), - enabledMarkup = emptyList(), - enabledAlignment = emptyList() - ) - } - Block.Content.File.Type.IMAGE -> { - StyleConfig( - visibleTypes = listOf(StylingType.BACKGROUND), - enabledMarkup = emptyList(), - enabledAlignment = emptyList() - ) - } - Block.Content.File.Type.VIDEO -> { - StyleConfig( - visibleTypes = listOf(StylingType.BACKGROUND), - enabledMarkup = emptyList(), - enabledAlignment = emptyList() - ) - } - else -> StyleConfig.emptyState() -} - -fun Block.Content.Text.getTextStyleConfig(focus: Boolean?, selection: IntRange?): StyleConfig { - return if (focus != null && focus) { - getStyleConfig(selection = selection) - } else { - getStyleConfig(selection = null) - } -} - -fun Block.Content.Text.getStyleConfig(selection: IntRange? = null): StyleConfig { - return if (selection == null || selection.first >= selection.last) { - getBlockStyle(style) - } else { - getMarkupStyle(style) - } -} - -fun Block.Content.Text.getSupportedMarkupTypes() : List = when(style) { - Block.Content.Text.Style.P -> { - listOf( - Markup.Type.BOLD, - Markup.Type.ITALIC, - Markup.Type.STRIKETHROUGH, - Markup.Type.KEYBOARD, - Markup.Type.LINK - ) - } - Block.Content.Text.Style.H1, Block.Content.Text.Style.H2, - Block.Content.Text.Style.H3, Block.Content.Text.Style.H4 -> { - listOf( - Markup.Type.ITALIC, - Markup.Type.STRIKETHROUGH, - Markup.Type.KEYBOARD, - Markup.Type.LINK - ) - } - Block.Content.Text.Style.QUOTE -> { - listOf( - Markup.Type.BOLD, - Markup.Type.ITALIC, - Markup.Type.STRIKETHROUGH, - Markup.Type.KEYBOARD, - Markup.Type.LINK - ) - } - Block.Content.Text.Style.BULLET, Block.Content.Text.Style.NUMBERED, - Block.Content.Text.Style.TOGGLE, Block.Content.Text.Style.CHECKBOX -> { - listOf( - Markup.Type.BOLD, - Markup.Type.ITALIC, - Markup.Type.STRIKETHROUGH, - Markup.Type.KEYBOARD, - Markup.Type.LINK - ) - } - else -> emptyList() -} - -fun Block.Content.Text.getBlockStyle(style: Block.Content.Text.Style) = when (style) { - Block.Content.Text.Style.P -> { - StyleConfig( - visibleTypes = listOf( - StylingType.STYLE, - StylingType.TEXT_COLOR, - StylingType.BACKGROUND - ), - enabledMarkup = listOf( - Markup.Type.BOLD, - Markup.Type.ITALIC, - Markup.Type.STRIKETHROUGH, - Markup.Type.KEYBOARD, - Markup.Type.LINK - ), - enabledAlignment = listOf(Alignment.START, Alignment.CENTER, Alignment.END) - ) - } - Block.Content.Text.Style.H1, Block.Content.Text.Style.H2, - Block.Content.Text.Style.H3, Block.Content.Text.Style.H4 -> { - StyleConfig( - visibleTypes = listOf( - StylingType.STYLE, - StylingType.TEXT_COLOR, - StylingType.BACKGROUND - ), - enabledMarkup = listOf( - Markup.Type.ITALIC, - Markup.Type.STRIKETHROUGH, - Markup.Type.KEYBOARD, - Markup.Type.LINK - ), - enabledAlignment = listOf(Alignment.START, Alignment.CENTER, Alignment.END) - ) - } - Block.Content.Text.Style.TITLE -> { - StyleConfig( - visibleTypes = listOf(StylingType.BACKGROUND), - enabledMarkup = emptyList(), - enabledAlignment = listOf(Alignment.START, Alignment.CENTER, Alignment.END) - ) - } - Block.Content.Text.Style.QUOTE -> { - StyleConfig( - visibleTypes = listOf( - StylingType.STYLE, - StylingType.TEXT_COLOR, - StylingType.BACKGROUND - ), - enabledMarkup = listOf( - Markup.Type.BOLD, - Markup.Type.ITALIC, - Markup.Type.STRIKETHROUGH, - Markup.Type.KEYBOARD, - Markup.Type.LINK - ), - enabledAlignment = listOf(Alignment.START, Alignment.END) - ) - } - Block.Content.Text.Style.CODE_SNIPPET -> { - StyleConfig( - visibleTypes = listOf(StylingType.BACKGROUND), - enabledMarkup = emptyList(), - enabledAlignment = emptyList() - ) - } - Block.Content.Text.Style.BULLET, Block.Content.Text.Style.NUMBERED, - Block.Content.Text.Style.TOGGLE, Block.Content.Text.Style.CHECKBOX -> { - StyleConfig( - visibleTypes = listOf( - StylingType.STYLE, - StylingType.TEXT_COLOR, - StylingType.BACKGROUND - ), - enabledMarkup = listOf( - Markup.Type.BOLD, - Markup.Type.ITALIC, - Markup.Type.STRIKETHROUGH, - Markup.Type.KEYBOARD, - Markup.Type.LINK - ), - enabledAlignment = emptyList() - ) - } - Block.Content.Text.Style.CALLOUT -> { - StyleConfig( - visibleTypes = listOf( - StylingType.STYLE, - StylingType.TEXT_COLOR, - StylingType.BACKGROUND - ), - enabledMarkup = listOf( - Markup.Type.BOLD, - Markup.Type.ITALIC, - Markup.Type.STRIKETHROUGH, - Markup.Type.KEYBOARD, - Markup.Type.LINK - ), - enabledAlignment = emptyList() - ) - } - Block.Content.Text.Style.DESCRIPTION -> throw IllegalStateException("Description block does not support styling") -} - -fun Block.Content.Text.getMarkupStyle(style: Block.Content.Text.Style) = when (style) { - Block.Content.Text.Style.P -> { - StyleConfig( - visibleTypes = listOf( - StylingType.STYLE, - StylingType.TEXT_COLOR, - StylingType.BACKGROUND - ), - enabledMarkup = listOf( - Markup.Type.BOLD, - Markup.Type.ITALIC, - Markup.Type.STRIKETHROUGH, - Markup.Type.KEYBOARD, - Markup.Type.LINK - ), - enabledAlignment = emptyList() - ) - } - Block.Content.Text.Style.H1, Block.Content.Text.Style.H2, - Block.Content.Text.Style.H3, Block.Content.Text.Style.H4 -> { - StyleConfig( - visibleTypes = listOf( - StylingType.STYLE, - StylingType.TEXT_COLOR, - StylingType.BACKGROUND - ), - enabledMarkup = listOf( - Markup.Type.ITALIC, - Markup.Type.STRIKETHROUGH, - Markup.Type.KEYBOARD, - Markup.Type.LINK - ), - enabledAlignment = emptyList() - ) - } - Block.Content.Text.Style.TITLE -> { - StyleConfig( - visibleTypes = listOf(StylingType.BACKGROUND), - enabledMarkup = emptyList(), - enabledAlignment = emptyList() - ) - } - Block.Content.Text.Style.QUOTE -> { - StyleConfig( - visibleTypes = listOf( - StylingType.STYLE, - StylingType.TEXT_COLOR, - StylingType.BACKGROUND - ), - enabledMarkup = listOf( - Markup.Type.BOLD, - Markup.Type.ITALIC, - Markup.Type.STRIKETHROUGH, - Markup.Type.KEYBOARD, - Markup.Type.LINK - ), - enabledAlignment = emptyList() - ) - } - Block.Content.Text.Style.CODE_SNIPPET -> { - StyleConfig( - visibleTypes = emptyList(), - enabledMarkup = emptyList(), - enabledAlignment = emptyList() - ) - } - Block.Content.Text.Style.BULLET, Block.Content.Text.Style.NUMBERED, - Block.Content.Text.Style.TOGGLE, Block.Content.Text.Style.CHECKBOX -> { - StyleConfig( - visibleTypes = listOf( - StylingType.STYLE, - StylingType.TEXT_COLOR, - StylingType.BACKGROUND - ), - enabledMarkup = listOf( - Markup.Type.BOLD, - Markup.Type.ITALIC, - Markup.Type.STRIKETHROUGH, - Markup.Type.KEYBOARD, - Markup.Type.LINK - ), - enabledAlignment = emptyList() - ) - } - Block.Content.Text.Style.CALLOUT -> { - StyleConfig( - visibleTypes = listOf( - StylingType.STYLE, - StylingType.TEXT_COLOR, - StylingType.BACKGROUND - ), - enabledMarkup = listOf( - Markup.Type.BOLD, - Markup.Type.ITALIC, - Markup.Type.STRIKETHROUGH, - Markup.Type.KEYBOARD, - Markup.Type.LINK - ), - enabledAlignment = emptyList() - ) - } - Block.Content.Text.Style.DESCRIPTION -> throw IllegalStateException("Description block does not support styling") -} - diff --git a/presentation/src/main/java/com/anytypeio/anytype/presentation/editor/editor/styling/StyleToolbarExt.kt b/presentation/src/main/java/com/anytypeio/anytype/presentation/editor/editor/styling/StyleToolbarExt.kt new file mode 100644 index 0000000000..257fdb43e1 --- /dev/null +++ b/presentation/src/main/java/com/anytypeio/anytype/presentation/editor/editor/styling/StyleToolbarExt.kt @@ -0,0 +1,165 @@ +package com.anytypeio.anytype.presentation.editor.editor.styling + +import com.anytypeio.anytype.core_models.Block +import com.anytypeio.anytype.core_models.Id +import com.anytypeio.anytype.presentation.editor.Editor +import com.anytypeio.anytype.presentation.editor.editor.Markup +import com.anytypeio.anytype.presentation.editor.editor.ThemeColor +import com.anytypeio.anytype.presentation.editor.editor.model.Alignment +import timber.log.Timber + +fun Editor.Mode.getIds(): List? = when (this) { + is Editor.Mode.Styling.Multi -> targets.toList() + is Editor.Mode.Styling.Single -> listOf(target) + else -> { + Timber.e("Couldn't get ids of selected blocks, wrong Editor Mode : $this") + null + } +} + +/** + * Checks that all block text contents have the same value of style and returns state with this value + * otherwise returns state with null + */ +fun List.getStyleTextToolbarState(): StyleToolbarState.Text { + val result = map { it.style }.distinct() + return if (result.size == 1) { + StyleToolbarState.Text( + textStyle = result[0] + ) + } else { + StyleToolbarState.Text( + textStyle = null + ) + } +} + +/** + * Checks that all blocks have the same value of background color and returns state with this value + * otherwise returns state with null + * We take as a statement that if block background value is null, then this block have default color + */ +fun List.getStyleBackgroundToolbarState(): StyleToolbarState.Background { + val result = map { it.backgroundColor ?: ThemeColor.DEFAULT.title }.distinct() + return if (result.size == 1) { + StyleToolbarState.Background( + background = result[0] + ) + } else { + StyleToolbarState.Background( + background = null + ) + } +} + +/** + * Checks that all blocks have the same value of background color and text color and returns state with this values + * otherwise returns state with null + * We take as a statement that if the block's background value is null + * or the block's text color is null, then this block has default background or text colors + */ +fun List.getStyleColorBackgroundToolbarState(): StyleToolbarState.ColorBackground { + val isAllText = all { it.content is Block.Content.Text } + if (!isAllText) return StyleToolbarState.ColorBackground.empty() + val resultColor = map { it.content.asText().color ?: ThemeColor.DEFAULT.title }.distinct() + val resultBackground = map { it.backgroundColor ?: ThemeColor.DEFAULT.title }.distinct() + return StyleToolbarState.ColorBackground( + background = if (resultBackground.size == 1) resultBackground[0] else null, + color = if (resultColor.size == 1) resultColor[0] else null + ) +} + +fun List.getStyleOtherToolbarState(): StyleToolbarState.Other { + val isSupportBold = all { it.isSupportBold() } + val isBoldSelected = if (isSupportBold) { + all { it.isBold() } + } else false + + return StyleToolbarState.Other( + isSupportBold = isSupportBold, + isSupportItalic = true, + isSupportCode = true, + isSupportLinked = true, + isSupportStrikethrough = true, + isSupportAlignStart = all { it.alignmentSupport().contains(Alignment.START) }, + isSupportAlignCenter = all { it.alignmentSupport().contains(Alignment.CENTER) }, + isSupportAlignEnd = all { it.alignmentSupport().contains(Alignment.END) }, + isBoldSelected = isBoldSelected, + isItalicSelected = all { it.isItalic() }, + isStrikethroughSelected = all { it.isStrikethrough() }, + isCodeSelected = all { it.isCode() }, + isLinkedSelected = all { it.isLinked() }, + isAlignCenterSelected = all { it.isAlignCenter() }, + isAlignStartSelected = all { it.isAlignStart() }, + isAlignEndSelected = all { it.isAlignEnd() } + ) +} + +private fun Block.Content.Text.isSupportBold(): Boolean = when (this.style) { + Block.Content.Text.Style.H1, + Block.Content.Text.Style.H2, + Block.Content.Text.Style.H3, + Block.Content.Text.Style.H4, + Block.Content.Text.Style.TITLE, + Block.Content.Text.Style.CODE_SNIPPET -> false + else -> true +} + +private fun Block.Content.Text.alignmentSupport(): List = when (this.style) { + Block.Content.Text.Style.P, + Block.Content.Text.Style.H1, + Block.Content.Text.Style.H2, + Block.Content.Text.Style.H3, + Block.Content.Text.Style.H4, + Block.Content.Text.Style.TITLE -> listOf(Alignment.START, Alignment.CENTER, Alignment.END) + Block.Content.Text.Style.QUOTE -> listOf(Alignment.START, Alignment.END) + else -> emptyList() +} + +fun Block.Content.Text.getSupportedMarkupTypes(): List = when (style) { + Block.Content.Text.Style.P, Block.Content.Text.Style.QUOTE, + Block.Content.Text.Style.BULLET, Block.Content.Text.Style.NUMBERED, + Block.Content.Text.Style.TOGGLE, Block.Content.Text.Style.CHECKBOX -> { + listOf( + Markup.Type.BOLD, + Markup.Type.ITALIC, + Markup.Type.STRIKETHROUGH, + Markup.Type.KEYBOARD, + Markup.Type.LINK + ) + } + Block.Content.Text.Style.H1, Block.Content.Text.Style.H2, + Block.Content.Text.Style.H3, Block.Content.Text.Style.H4 -> { + listOf( + Markup.Type.ITALIC, + Markup.Type.STRIKETHROUGH, + Markup.Type.KEYBOARD, + Markup.Type.LINK + ) + } + else -> emptyList() +} + +fun Block.Content.Text.isBold(): Boolean = marks.any { mark -> + mark.type == Block.Content.Text.Mark.Type.BOLD && mark.range.first == 0 && mark.range.last == text.length +} + +fun Block.Content.Text.isItalic(): Boolean = marks.any { mark -> + mark.type == Block.Content.Text.Mark.Type.ITALIC && mark.range.first == 0 && mark.range.last == text.length +} + +fun Block.Content.Text.isStrikethrough(): Boolean = marks.any { mark -> + mark.type == Block.Content.Text.Mark.Type.STRIKETHROUGH && mark.range.first == 0 && mark.range.last == text.length +} + +fun Block.Content.Text.isCode(): Boolean = marks.any { mark -> + mark.type == Block.Content.Text.Mark.Type.KEYBOARD && mark.range.first == 0 && mark.range.last == text.length +} + +fun Block.Content.Text.isLinked(): Boolean = marks.any { mark -> + mark.type == Block.Content.Text.Mark.Type.LINK && mark.range.first == 0 && mark.range.last == text.length +} + +fun Block.Content.Text.isAlignStart(): Boolean = this.align == Block.Align.AlignLeft +fun Block.Content.Text.isAlignCenter(): Boolean = this.align == Block.Align.AlignCenter +fun Block.Content.Text.isAlignEnd(): Boolean = this.align == Block.Align.AlignRight diff --git a/presentation/src/main/java/com/anytypeio/anytype/presentation/editor/editor/styling/StyleToolbarState.kt b/presentation/src/main/java/com/anytypeio/anytype/presentation/editor/editor/styling/StyleToolbarState.kt new file mode 100644 index 0000000000..19cdc27cd2 --- /dev/null +++ b/presentation/src/main/java/com/anytypeio/anytype/presentation/editor/editor/styling/StyleToolbarState.kt @@ -0,0 +1,48 @@ +package com.anytypeio.anytype.presentation.editor.editor.styling + +import com.anytypeio.anytype.core_models.TextStyle +import com.anytypeio.anytype.presentation.editor.editor.model.Alignment + +sealed class StyleToolbarState { + + data class Text(val textStyle: TextStyle?) : StyleToolbarState() { + companion object { + fun empty() = Text(null) + } + } + + data class Other( + val isSupportBold: Boolean = false, + val isSupportItalic: Boolean = false, + val isSupportStrikethrough: Boolean = false, + val isSupportCode: Boolean = false, + val isSupportLinked: Boolean = false, + val isSupportAlignStart: Boolean = false, + val isSupportAlignCenter: Boolean = false, + val isSupportAlignEnd: Boolean = false, + val isBoldSelected: Boolean = false, + val isItalicSelected: Boolean = false, + val isStrikethroughSelected: Boolean = false, + val isCodeSelected: Boolean = false, + val isLinkedSelected: Boolean = false, + val isAlignStartSelected: Boolean = false, + val isAlignCenterSelected: Boolean = false, + val isAlignEndSelected: Boolean = false + ) : StyleToolbarState() { + companion object { + fun empty() = Other() + } + } + + data class ColorBackground(val color: String?, val background: String?) : StyleToolbarState() { + companion object { + fun empty() = ColorBackground(null, null) + } + } + + data class Background(val background: String?) : StyleToolbarState() { + companion object { + fun empty() = Background(null) + } + } +} diff --git a/presentation/src/main/java/com/anytypeio/anytype/presentation/mapper/MapperExtension.kt b/presentation/src/main/java/com/anytypeio/anytype/presentation/mapper/MapperExtension.kt index a9f7aa21db..331e03dc7d 100644 --- a/presentation/src/main/java/com/anytypeio/anytype/presentation/mapper/MapperExtension.kt +++ b/presentation/src/main/java/com/anytypeio/anytype/presentation/mapper/MapperExtension.kt @@ -727,20 +727,6 @@ fun ObjectLayoutView.toObjectLayout() = when (this) { is ObjectLayoutView.Todo -> ObjectType.Layout.TODO } -fun List.getPropsForSelectedTextBlocks(): ControlPanelState.Toolbar.Styling.Props { - val colors = map { it.textColor() ?: ThemeColor.DEFAULT.title }.distinct() - val selectedColor = if (colors.size == 1) colors[0] else null - return ControlPanelState.Toolbar.Styling.Props( - color = selectedColor, - background = this.getSelectedBackgroundForSelectedBlocks() - ) -} - -fun List.getSelectedBackgroundForSelectedBlocks(): String? { - val backgrounds = map { it.backgroundColor ?: ThemeColor.DEFAULT.title }.distinct() - return if (backgrounds.size == 1) backgrounds[0] else null -} - fun List.getTextStyleForSelectedTextBlocks(): Block.Content.Text.Style? { val styles = map { it.textStyle() }.distinct() return if (styles.size == 1) styles[0] else null diff --git a/presentation/src/test/java/com/anytypeio/anytype/presentation/MockBlockFactory.kt b/presentation/src/test/java/com/anytypeio/anytype/presentation/MockBlockFactory.kt index 7acb8d10f2..c60ad79ce5 100644 --- a/presentation/src/test/java/com/anytypeio/anytype/presentation/MockBlockFactory.kt +++ b/presentation/src/test/java/com/anytypeio/anytype/presentation/MockBlockFactory.kt @@ -52,7 +52,8 @@ object MockBlockFactory { fun makeOnePageWithOneTextBlock( root: String, child: String, - style: Block.Content.Text.Style = Block.Content.Text.Style.P + style: Block.Content.Text.Style = Block.Content.Text.Style.P, + backgroundColor: String? = null ) = listOf( Block( id = root, @@ -68,7 +69,8 @@ object MockBlockFactory { marks = emptyList(), style = style ), - children = emptyList() + children = emptyList(), + backgroundColor = backgroundColor ) ) diff --git a/presentation/src/test/java/com/anytypeio/anytype/presentation/editor/ControlPanelStateReducerTest.kt b/presentation/src/test/java/com/anytypeio/anytype/presentation/editor/ControlPanelStateReducerTest.kt index 358fb2792b..6f88799144 100644 --- a/presentation/src/test/java/com/anytypeio/anytype/presentation/editor/ControlPanelStateReducerTest.kt +++ b/presentation/src/test/java/com/anytypeio/anytype/presentation/editor/ControlPanelStateReducerTest.kt @@ -1,13 +1,12 @@ package com.anytypeio.anytype.presentation.editor import com.anytypeio.anytype.core_models.Block +import com.anytypeio.anytype.core_models.TextStyle import com.anytypeio.anytype.domain.config.Gateway import com.anytypeio.anytype.domain.misc.UrlBuilder import com.anytypeio.anytype.presentation.editor.editor.Markup import com.anytypeio.anytype.presentation.editor.editor.control.ControlPanelState -import com.anytypeio.anytype.presentation.editor.editor.model.Alignment -import com.anytypeio.anytype.presentation.editor.editor.styling.StyleConfig -import com.anytypeio.anytype.presentation.editor.editor.styling.StylingType +import com.anytypeio.anytype.presentation.editor.editor.styling.StyleToolbarState import com.anytypeio.anytype.presentation.editor.markup.MarkupStyleDescriptor import com.anytypeio.anytype.presentation.util.CoroutinesTestRule import com.anytypeio.anytype.test_utils.MockDataFactory @@ -84,26 +83,11 @@ class ControlPanelStateReducerTest { fun `state should hide mentions when cursor before mentions start and widget is visible`() { val given = ControlPanelState( - navigationToolbar = ControlPanelState.Toolbar.Navigation( - isVisible = false - ), - mainToolbar = ControlPanelState.Toolbar.Main( - isVisible = false - ), - styleTextToolbar = ControlPanelState.Toolbar.Styling( - isVisible = false - ), - multiSelect = ControlPanelState.Toolbar.MultiSelect( - isVisible = false - ), mentionToolbar = ControlPanelState.Toolbar.MentionToolbar( isVisible = true, cursorCoordinate = 333, mentionFilter = "start", mentionFrom = 10 - ), - slashWidget = ControlPanelState.Toolbar.SlashWidget( - isVisible = false ) ) @@ -141,26 +125,11 @@ class ControlPanelStateReducerTest { fun `state should not hide mentions when cursor after mention start`() { val given = ControlPanelState( - navigationToolbar = ControlPanelState.Toolbar.Navigation( - isVisible = false - ), - mainToolbar = ControlPanelState.Toolbar.Main( - isVisible = true - ), - styleTextToolbar = ControlPanelState.Toolbar.Styling( - isVisible = false - ), - multiSelect = ControlPanelState.Toolbar.MultiSelect( - isVisible = false - ), mentionToolbar = ControlPanelState.Toolbar.MentionToolbar( isVisible = true, cursorCoordinate = 333, mentionFilter = "start", mentionFrom = 10 - ), - slashWidget = ControlPanelState.Toolbar.SlashWidget( - isVisible = false ) ) @@ -195,26 +164,11 @@ class ControlPanelStateReducerTest { fun `state should hide mentions after focus changed`() { val given = ControlPanelState( - navigationToolbar = ControlPanelState.Toolbar.Navigation( - isVisible = false - ), - mainToolbar = ControlPanelState.Toolbar.Main( - isVisible = true - ), - styleTextToolbar = ControlPanelState.Toolbar.Styling( - isVisible = false - ), - multiSelect = ControlPanelState.Toolbar.MultiSelect( - isVisible = false - ), mentionToolbar = ControlPanelState.Toolbar.MentionToolbar( isVisible = true, cursorCoordinate = 333, mentionFilter = "start", mentionFrom = 10 - ), - slashWidget = ControlPanelState.Toolbar.SlashWidget( - isVisible = false ) ) @@ -236,7 +190,8 @@ class ControlPanelStateReducerTest { cursorCoordinate = null, mentionFilter = null, mentionFrom = null - ) + ), + mainToolbar = ControlPanelState.Toolbar.Main(isVisible = true) ) assertEquals( @@ -251,26 +206,11 @@ class ControlPanelStateReducerTest { val id = MockDataFactory.randomUuid() val given = ControlPanelState( - navigationToolbar = ControlPanelState.Toolbar.Navigation( - isVisible = false - ), - mainToolbar = ControlPanelState.Toolbar.Main( - isVisible = false, - ), - styleTextToolbar = ControlPanelState.Toolbar.Styling( - isVisible = false - ), - multiSelect = ControlPanelState.Toolbar.MultiSelect( - isVisible = false - ), mentionToolbar = ControlPanelState.Toolbar.MentionToolbar( isVisible = true, cursorCoordinate = 333, mentionFilter = "start", mentionFrom = 10 - ), - slashWidget = ControlPanelState.Toolbar.SlashWidget( - isVisible = false ) ) @@ -317,26 +257,8 @@ class ControlPanelStateReducerTest { fun `state should have only focus changed`() { val given = ControlPanelState( - navigationToolbar = ControlPanelState.Toolbar.Navigation( - isVisible = false - ), mainToolbar = ControlPanelState.Toolbar.Main( isVisible = true - ), - styleTextToolbar = ControlPanelState.Toolbar.Styling( - isVisible = false - ), - multiSelect = ControlPanelState.Toolbar.MultiSelect( - isVisible = false - ), - mentionToolbar = ControlPanelState.Toolbar.MentionToolbar( - isVisible = false, - cursorCoordinate = null, - mentionFilter = null, - mentionFrom = null - ), - slashWidget = ControlPanelState.Toolbar.SlashWidget( - isVisible = false ) ) @@ -364,26 +286,14 @@ class ControlPanelStateReducerTest { fun `should return to initial state when focus is cleared`() { val given = ControlPanelState( - navigationToolbar = ControlPanelState.Toolbar.Navigation( - isVisible = false - ), mainToolbar = ControlPanelState.Toolbar.Main( isVisible = true ), - styleTextToolbar = ControlPanelState.Toolbar.Styling( - isVisible = false - ), - multiSelect = ControlPanelState.Toolbar.MultiSelect( - isVisible = false - ), mentionToolbar = ControlPanelState.Toolbar.MentionToolbar( isVisible = false, cursorCoordinate = null, mentionFilter = null, mentionFrom = null - ), - slashWidget = ControlPanelState.Toolbar.SlashWidget( - isVisible = false ) ) @@ -410,15 +320,6 @@ class ControlPanelStateReducerTest { val id = MockDataFactory.randomUuid() val nonSelected = ControlPanelState( - navigationToolbar = ControlPanelState.Toolbar.Navigation( - isVisible = false - ), - mainToolbar = ControlPanelState.Toolbar.Main( - isVisible = false - ), - styleTextToolbar = ControlPanelState.Toolbar.Styling( - isVisible = false - ), multiSelect = ControlPanelState.Toolbar.MultiSelect( isVisible = false, count = 2 @@ -428,34 +329,13 @@ class ControlPanelStateReducerTest { cursorCoordinate = null, mentionFilter = null, mentionFrom = null - ), - slashWidget = ControlPanelState.Toolbar.SlashWidget( - isVisible = false ) ) val selected = ControlPanelState( - navigationToolbar = ControlPanelState.Toolbar.Navigation( - isVisible = false - ), - mainToolbar = ControlPanelState.Toolbar.Main( - isVisible = false - ), - styleTextToolbar = ControlPanelState.Toolbar.Styling( - isVisible = false - ), multiSelect = ControlPanelState.Toolbar.MultiSelect( isVisible = true, count = 0 - ), - mentionToolbar = ControlPanelState.Toolbar.MentionToolbar( - isVisible = false, - cursorCoordinate = null, - mentionFilter = null, - mentionFrom = null - ), - slashWidget = ControlPanelState.Toolbar.SlashWidget( - isVisible = false ) ) @@ -478,52 +358,16 @@ class ControlPanelStateReducerTest { val id = MockDataFactory.randomUuid() val selectedZero = ControlPanelState( - navigationToolbar = ControlPanelState.Toolbar.Navigation( - isVisible = false - ), - mainToolbar = ControlPanelState.Toolbar.Main( - isVisible = false - ), - styleTextToolbar = ControlPanelState.Toolbar.Styling( - isVisible = false - ), multiSelect = ControlPanelState.Toolbar.MultiSelect( isVisible = true, count = 0 - ), - mentionToolbar = ControlPanelState.Toolbar.MentionToolbar( - isVisible = false, - cursorCoordinate = null, - mentionFilter = null, - mentionFrom = null - ), - slashWidget = ControlPanelState.Toolbar.SlashWidget( - isVisible = false ) ) val expected = ControlPanelState( - navigationToolbar = ControlPanelState.Toolbar.Navigation( - isVisible = false - ), - mainToolbar = ControlPanelState.Toolbar.Main( - isVisible = false - ), - styleTextToolbar = ControlPanelState.Toolbar.Styling( - isVisible = false - ), multiSelect = ControlPanelState.Toolbar.MultiSelect( isVisible = true, count = 3 - ), - mentionToolbar = ControlPanelState.Toolbar.MentionToolbar( - isVisible = false, - cursorCoordinate = null, - mentionFilter = null, - mentionFrom = null - ), - slashWidget = ControlPanelState.Toolbar.SlashWidget( - isVisible = false ) ) @@ -541,123 +385,124 @@ class ControlPanelStateReducerTest { } @Test - fun `should update style toolbar state with italic true after selection changed`() = runBlocking { + fun `should update style toolbar state with italic true after selection changed`() = + runBlocking { - val block = Block( - id = MockDataFactory.randomUuid(), - children = emptyList(), - content = Block.Content.Text( - text = "Foo Bar", - style = Block.Content.Text.Style.P, - marks = listOf( - Block.Content.Text.Mark( + val block = Block( + id = MockDataFactory.randomUuid(), + children = emptyList(), + content = Block.Content.Text( + text = "Foo Bar", + style = Block.Content.Text.Style.P, + marks = listOf( + Block.Content.Text.Mark( + range = IntRange(0, 2), + type = Block.Content.Text.Mark.Type.BOLD + ), + Block.Content.Text.Mark( + range = IntRange(4, 6), + type = Block.Content.Text.Mark.Type.ITALIC + ) + ) + ), + fields = Block.Fields.empty() + ) + + val selectionFirst = IntRange(0, 2) + val selectionSecond = IntRange(4, 6) + + val given = ControlPanelState( + styleTextToolbar = ControlPanelState.Toolbar.Styling.reset(), + navigationToolbar = ControlPanelState.Toolbar.Navigation.reset(), + mainToolbar = ControlPanelState.Toolbar.Main.reset(), + multiSelect = ControlPanelState.Toolbar.MultiSelect.reset(), + mentionToolbar = ControlPanelState.Toolbar.MentionToolbar.reset(), + slashWidget = ControlPanelState.Toolbar.SlashWidget.reset(), + markupMainToolbar = ControlPanelState.Toolbar.MarkupMainToolbar( + isVisible = true, + style = MarkupStyleDescriptor.Default( + isBold = true, + isItalic = false, + isCode = false, + isLinked = false, + isStrikethrough = false, + markupTextColor = "yellow", + markupUrl = null, + markupHighlightColor = "red", range = IntRange(0, 2), - type = Block.Content.Text.Mark.Type.BOLD + blockBackroundColor = null, + blockTextColor = null ), - Block.Content.Text.Mark( - range = IntRange(4, 6), - type = Block.Content.Text.Mark.Type.ITALIC + supportedTypes = listOf( + Markup.Type.BOLD, + Markup.Type.ITALIC, + Markup.Type.STRIKETHROUGH, + Markup.Type.KEYBOARD, + Markup.Type.LINK ) ) - ), - fields = Block.Fields.empty() - ) + ) - val selectionFirst = IntRange(0, 2) - val selectionSecond = IntRange(4, 6) + val result = runBlocking { + reducer.reduce( + state = given, + event = ControlPanelMachine.Event.OnSelectionChanged( + selection = selectionSecond, + target = block + ) + ) + } - val given = ControlPanelState( - styleTextToolbar = ControlPanelState.Toolbar.Styling.reset(), - navigationToolbar = ControlPanelState.Toolbar.Navigation.reset(), - mainToolbar = ControlPanelState.Toolbar.Main.reset(), - multiSelect = ControlPanelState.Toolbar.MultiSelect.reset(), - mentionToolbar = ControlPanelState.Toolbar.MentionToolbar.reset(), - slashWidget = ControlPanelState.Toolbar.SlashWidget.reset(), - markupMainToolbar = ControlPanelState.Toolbar.MarkupMainToolbar( - isVisible = true, - style = MarkupStyleDescriptor.Default( - isBold = true, - isItalic = false, - isCode = false, - isLinked = false, - isStrikethrough = false, - markupTextColor = "yellow", - markupUrl = null, - markupHighlightColor = "red", - range = IntRange(0, 2), - blockBackroundColor = null, - blockTextColor = null + val expected = ControlPanelState( + navigationToolbar = ControlPanelState.Toolbar.Navigation( + isVisible = false ), - supportedTypes = listOf( - Markup.Type.BOLD, - Markup.Type.ITALIC, - Markup.Type.STRIKETHROUGH, - Markup.Type.KEYBOARD, - Markup.Type.LINK + mainToolbar = ControlPanelState.Toolbar.Main( + isVisible = false + ), + styleTextToolbar = ControlPanelState.Toolbar.Styling.reset(), + multiSelect = ControlPanelState.Toolbar.MultiSelect( + isVisible = false + ), + mentionToolbar = ControlPanelState.Toolbar.MentionToolbar( + isVisible = false, + cursorCoordinate = null, + mentionFilter = null, + mentionFrom = null + ), + slashWidget = ControlPanelState.Toolbar.SlashWidget( + isVisible = false + ), + markupMainToolbar = ControlPanelState.Toolbar.MarkupMainToolbar( + isVisible = true, + style = MarkupStyleDescriptor.Default( + isBold = false, + isItalic = true, + isCode = false, + isLinked = false, + isStrikethrough = false, + markupTextColor = null, + markupUrl = null, + markupHighlightColor = null, + range = IntRange(4, 6), + blockBackroundColor = null, + blockTextColor = null + ), + supportedTypes = listOf( + Markup.Type.BOLD, + Markup.Type.ITALIC, + Markup.Type.STRIKETHROUGH, + Markup.Type.KEYBOARD, + Markup.Type.LINK + ) ) ) - ) - - val result = runBlocking { - reducer.reduce( - state = given, - event = ControlPanelMachine.Event.OnSelectionChanged( - selection = selectionSecond, - target = block - ) + assertEquals( + expected = expected, + actual = result ) } - val expected = ControlPanelState( - navigationToolbar = ControlPanelState.Toolbar.Navigation( - isVisible = false - ), - mainToolbar = ControlPanelState.Toolbar.Main( - isVisible = false - ), - styleTextToolbar = ControlPanelState.Toolbar.Styling.reset(), - multiSelect = ControlPanelState.Toolbar.MultiSelect( - isVisible = false - ), - mentionToolbar = ControlPanelState.Toolbar.MentionToolbar( - isVisible = false, - cursorCoordinate = null, - mentionFilter = null, - mentionFrom = null - ), - slashWidget = ControlPanelState.Toolbar.SlashWidget( - isVisible = false - ), - markupMainToolbar = ControlPanelState.Toolbar.MarkupMainToolbar( - isVisible = true, - style = MarkupStyleDescriptor.Default( - isBold = false, - isItalic = true, - isCode = false, - isLinked = false, - isStrikethrough = false, - markupTextColor = null, - markupUrl = null, - markupHighlightColor = null, - range = IntRange(4, 6), - blockBackroundColor = null, - blockTextColor = null - ), - supportedTypes = listOf( - Markup.Type.BOLD, - Markup.Type.ITALIC, - Markup.Type.STRIKETHROUGH, - Markup.Type.KEYBOARD, - Markup.Type.LINK - ) - ) - ) - assertEquals( - expected = expected, - actual = result - ) - } - @Test fun `should show style toolbar in markup mode after main toolbar style clicked`() { @@ -693,19 +538,8 @@ class ControlPanelStateReducerTest { } val given = ControlPanelState( - navigationToolbar = ControlPanelState.Toolbar.Navigation( - isVisible = false - ), mainToolbar = ControlPanelState.Toolbar.Main( isVisible = true - ), - styleTextToolbar = ControlPanelState.Toolbar.Styling.reset(), - multiSelect = ControlPanelState.Toolbar.MultiSelect( - isVisible = false - ), - mentionToolbar = ControlPanelState.Toolbar.MentionToolbar.reset(), - slashWidget = ControlPanelState.Toolbar.SlashWidget( - isVisible = false ) ) @@ -722,12 +556,8 @@ class ControlPanelStateReducerTest { val result = runBlocking { reducer.reduce( state = given, - event = ControlPanelMachine.Event.OnBlockActionToolbarStyleClicked( - target = block, - selection = IntRange(0, 3), - focused = true, - urlBuilder = urlBuilder, - details = Block.Details(mapOf()) + event = ControlPanelMachine.Event.StylingToolbar.OnUpdateTextToolbar( + state = StyleToolbarState.Text(textStyle = Block.Content.Text.Style.P) ) ) } @@ -740,40 +570,8 @@ class ControlPanelStateReducerTest { isVisible = false ), styleTextToolbar = ControlPanelState.Toolbar.Styling( - isVisible = true, - target = ControlPanelState.Toolbar.Styling.Target( - id = id, - text = "Foo Bar", - color = "yellow", - background = "red", - alignment = Alignment.START, - marks = listOf(Markup.Mark.Bold(0, 3)) - ), - config = StyleConfig( - visibleTypes = listOf( - StylingType.STYLE, - StylingType.TEXT_COLOR, - StylingType.BACKGROUND - ), - enabledAlignment = listOf(), - enabledMarkup = listOf( - Markup.Type.BOLD, - Markup.Type.ITALIC, - Markup.Type.STRIKETHROUGH, - Markup.Type.KEYBOARD, - Markup.Type.LINK - ) - ), - props = ControlPanelState.Toolbar.Styling.Props( - isBold = true, - isItalic = false, - isStrikethrough = false, - isCode = false, - isLinked = false, - alignment = Alignment.START, - color = "yellow", - background = "red" - ) + state = StyleToolbarState.Text(Block.Content.Text.Style.P), + isVisible = true ), multiSelect = ControlPanelState.Toolbar.MultiSelect( isVisible = false @@ -797,7 +595,7 @@ class ControlPanelStateReducerTest { children = emptyList(), content = Block.Content.Text( text = "Foo Bar", - style = Block.Content.Text.Style.P, + style = Block.Content.Text.Style.BULLET, marks = listOf( Block.Content.Text.Mark( range = 0..3, @@ -816,7 +614,7 @@ class ControlPanelStateReducerTest { state = ControlPanelState.init(), event = ControlPanelMachine.Event.OnFocusChanged( id = id, - style = Block.Content.Text.Style.P + style = Block.Content.Text.Style.BULLET ) ) } @@ -832,87 +630,25 @@ class ControlPanelStateReducerTest { } val given = ControlPanelState( - navigationToolbar = ControlPanelState.Toolbar.Navigation( - isVisible = false - ), mainToolbar = ControlPanelState.Toolbar.Main( isVisible = true - ), - styleTextToolbar = ControlPanelState.Toolbar.Styling.reset(), - multiSelect = ControlPanelState.Toolbar.MultiSelect( - isVisible = false - ), - mentionToolbar = ControlPanelState.Toolbar.MentionToolbar.reset(), - slashWidget = ControlPanelState.Toolbar.SlashWidget.reset() + ) ) val result = runBlocking { reducer.reduce( state = given, - event = ControlPanelMachine.Event.OnBlockActionToolbarStyleClicked( - target = block, - selection = IntRange(1, 1), - focused = true, - urlBuilder = urlBuilder, - details = Block.Details(mapOf()) + event = ControlPanelMachine.Event.StylingToolbar.OnUpdateTextToolbar( + state = StyleToolbarState.Text(textStyle = Block.Content.Text.Style.BULLET) ) ) } val expected = ControlPanelState( - navigationToolbar = ControlPanelState.Toolbar.Navigation( - isVisible = false - ), - mainToolbar = ControlPanelState.Toolbar.Main( - isVisible = false - ), styleTextToolbar = ControlPanelState.Toolbar.Styling( - isVisible = true, - target = ControlPanelState.Toolbar.Styling.Target( - id = id, - text = "Foo Bar", - color = "yellow", - background = "red", - alignment = Alignment.CENTER, - marks = listOf( - Markup.Mark.Bold(0, 3) - ) - ), - config = StyleConfig( - visibleTypes = listOf( - StylingType.STYLE, - StylingType.TEXT_COLOR, - StylingType.BACKGROUND - ), - enabledAlignment = listOf( - Alignment.START, - Alignment.CENTER, - Alignment.END - ), - enabledMarkup = listOf( - Markup.Type.BOLD, - Markup.Type.ITALIC, - Markup.Type.STRIKETHROUGH, - Markup.Type.KEYBOARD, - Markup.Type.LINK - ) - ), - props = ControlPanelState.Toolbar.Styling.Props( - isBold = false, - isItalic = false, - isStrikethrough = false, - isCode = false, - isLinked = false, - alignment = Alignment.CENTER, - color = "yellow", - background = "red" - ) - ), - multiSelect = ControlPanelState.Toolbar.MultiSelect( - isVisible = false - ), - mentionToolbar = ControlPanelState.Toolbar.MentionToolbar.reset(), - slashWidget = ControlPanelState.Toolbar.SlashWidget.reset() + state = StyleToolbarState.Text(textStyle = TextStyle.BULLET), + isVisible = true + ) ) assertEquals( expected = expected, @@ -987,12 +723,6 @@ class ControlPanelStateReducerTest { ) val expected = ControlPanelState( - styleTextToolbar = ControlPanelState.Toolbar.Styling.reset(), - navigationToolbar = ControlPanelState.Toolbar.Navigation.reset(), - mainToolbar = ControlPanelState.Toolbar.Main.reset(), - multiSelect = ControlPanelState.Toolbar.MultiSelect.reset(), - mentionToolbar = ControlPanelState.Toolbar.MentionToolbar.reset(), - slashWidget = ControlPanelState.Toolbar.SlashWidget.reset(), markupMainToolbar = ControlPanelState.Toolbar.MarkupMainToolbar( isVisible = true, style = MarkupStyleDescriptor.Default( diff --git a/presentation/src/test/java/com/anytypeio/anytype/presentation/editor/EditorViewModelTest.kt b/presentation/src/test/java/com/anytypeio/anytype/presentation/editor/EditorViewModelTest.kt index d61a3faf3f..f5deb02a18 100644 --- a/presentation/src/test/java/com/anytypeio/anytype/presentation/editor/EditorViewModelTest.kt +++ b/presentation/src/test/java/com/anytypeio/anytype/presentation/editor/EditorViewModelTest.kt @@ -77,7 +77,6 @@ import com.anytypeio.anytype.presentation.editor.editor.Interactor import com.anytypeio.anytype.presentation.editor.editor.InternalDetailModificationManager import com.anytypeio.anytype.presentation.editor.editor.Markup import com.anytypeio.anytype.presentation.editor.editor.Orchestrator -import com.anytypeio.anytype.presentation.editor.editor.ThemeColor import com.anytypeio.anytype.presentation.editor.editor.ViewState import com.anytypeio.anytype.presentation.editor.editor.actions.ActionItemType import com.anytypeio.anytype.presentation.editor.editor.control.ControlPanelState @@ -85,7 +84,7 @@ import com.anytypeio.anytype.presentation.editor.editor.listener.ListenerType import com.anytypeio.anytype.presentation.editor.editor.model.BlockView import com.anytypeio.anytype.presentation.editor.editor.model.UiBlock import com.anytypeio.anytype.presentation.editor.editor.pattern.DefaultPatternMatcher -import com.anytypeio.anytype.presentation.editor.editor.styling.StyleConfig +import com.anytypeio.anytype.presentation.editor.editor.styling.StyleToolbarState import com.anytypeio.anytype.presentation.editor.editor.styling.StylingEvent import com.anytypeio.anytype.presentation.editor.render.DefaultBlockViewRenderer import com.anytypeio.anytype.presentation.editor.selection.SelectionStateHolder @@ -4531,12 +4530,7 @@ open class EditorViewModelTest { ), styleTextToolbar = ControlPanelState.Toolbar.Styling( isVisible = true, - style = Block.Content.Text.Style.P, - config = StyleConfig.emptyState(), - props = ControlPanelState.Toolbar.Styling.Props( - color = ThemeColor.DEFAULT.title, - background = ThemeColor.DEFAULT.title - ) + state = StyleToolbarState.Text(Block.Content.Text.Style.P) ), multiSelect = ControlPanelState.Toolbar.MultiSelect( isVisible = true, diff --git a/presentation/src/test/java/com/anytypeio/anytype/presentation/editor/editor/EditorMultiSelectModeTest.kt b/presentation/src/test/java/com/anytypeio/anytype/presentation/editor/editor/EditorMultiSelectModeTest.kt index 9cecde0f7d..23817daa33 100644 --- a/presentation/src/test/java/com/anytypeio/anytype/presentation/editor/editor/EditorMultiSelectModeTest.kt +++ b/presentation/src/test/java/com/anytypeio/anytype/presentation/editor/editor/EditorMultiSelectModeTest.kt @@ -18,7 +18,7 @@ import com.anytypeio.anytype.presentation.editor.editor.control.ControlPanelStat import com.anytypeio.anytype.presentation.editor.editor.listener.ListenerType import com.anytypeio.anytype.presentation.editor.editor.model.BlockView import com.anytypeio.anytype.presentation.editor.editor.model.UiBlock -import com.anytypeio.anytype.presentation.editor.editor.styling.StyleConfig +import com.anytypeio.anytype.presentation.editor.editor.styling.StyleToolbarState import com.anytypeio.anytype.presentation.util.CoroutinesTestRule import com.anytypeio.anytype.presentation.util.TXT import com.anytypeio.anytype.test_utils.MockDataFactory @@ -149,27 +149,11 @@ class EditorMultiSelectModeTest : EditorPresentationTestSetup() { vm.controlPanelViewState.test().apply { assertValue( ControlPanelState( - navigationToolbar = ControlPanelState.Toolbar.Navigation( - isVisible = false - ), - mainToolbar = ControlPanelState.Toolbar.Main( - isVisible = false - ), - styleTextToolbar = ControlPanelState.Toolbar.Styling( - isVisible = false - ), multiSelect = ControlPanelState.Toolbar.MultiSelect( isVisible = true, isScrollAndMoveEnabled = false, count = 0 - ), - mentionToolbar = ControlPanelState.Toolbar.MentionToolbar( - isVisible = false, - cursorCoordinate = null, - mentionFilter = null, - mentionFrom = null - ), - slashWidget = ControlPanelState.Toolbar.SlashWidget.reset() + ) ) ) } @@ -249,27 +233,11 @@ class EditorMultiSelectModeTest : EditorPresentationTestSetup() { vm.controlPanelViewState.test().apply { assertValue( ControlPanelState( - navigationToolbar = ControlPanelState.Toolbar.Navigation( - isVisible = false - ), - mainToolbar = ControlPanelState.Toolbar.Main( - isVisible = false - ), - styleTextToolbar = ControlPanelState.Toolbar.Styling( - isVisible = false - ), multiSelect = ControlPanelState.Toolbar.MultiSelect( isVisible = true, isScrollAndMoveEnabled = false, count = 0 - ), - mentionToolbar = ControlPanelState.Toolbar.MentionToolbar( - isVisible = false, - cursorCoordinate = null, - mentionFilter = null, - mentionFrom = null - ), - slashWidget = ControlPanelState.Toolbar.SlashWidget.reset() + ) ) ) } @@ -365,27 +333,11 @@ class EditorMultiSelectModeTest : EditorPresentationTestSetup() { vm.controlPanelViewState.test().apply { assertValue( ControlPanelState( - navigationToolbar = ControlPanelState.Toolbar.Navigation( - isVisible = false - ), - mainToolbar = ControlPanelState.Toolbar.Main( - isVisible = false - ), - styleTextToolbar = ControlPanelState.Toolbar.Styling( - isVisible = false - ), multiSelect = ControlPanelState.Toolbar.MultiSelect( isVisible = true, isScrollAndMoveEnabled = false, count = 0 - ), - mentionToolbar = ControlPanelState.Toolbar.MentionToolbar( - isVisible = false, - cursorCoordinate = null, - mentionFilter = null, - mentionFrom = null - ), - slashWidget = ControlPanelState.Toolbar.SlashWidget.reset() + ) ) ) } @@ -1336,12 +1288,7 @@ class EditorMultiSelectModeTest : EditorPresentationTestSetup() { val expectedState = ControlPanelState( styleTextToolbar = ControlPanelState.Toolbar.Styling( isVisible = true, - style = null, - config = StyleConfig.emptyState(), - props = ControlPanelState.Toolbar.Styling.Props( - color = ThemeColor.DEFAULT.title, - background = ThemeColor.DEFAULT.title - ) + state = StyleToolbarState.Text(null) ), multiSelect = ControlPanelState.Toolbar.MultiSelect( isVisible = true, @@ -1429,7 +1376,7 @@ class EditorMultiSelectModeTest : EditorPresentationTestSetup() { ), styleBackgroundToolbar = ControlPanelState.Toolbar.Styling.Background( isVisible = true, - selectedBackground = null + state = StyleToolbarState.Background(background = null) ) ) @@ -1510,7 +1457,7 @@ class EditorMultiSelectModeTest : EditorPresentationTestSetup() { ), styleBackgroundToolbar = ControlPanelState.Toolbar.Styling.Background( isVisible = true, - selectedBackground = backgroundA + state = StyleToolbarState.Background(background = backgroundA) ) ) @@ -1593,7 +1540,7 @@ class EditorMultiSelectModeTest : EditorPresentationTestSetup() { ), styleBackgroundToolbar = ControlPanelState.Toolbar.Styling.Background( isVisible = true, - selectedBackground = backgroundA + state = StyleToolbarState.Background(background = backgroundA) ) ) @@ -1674,7 +1621,7 @@ class EditorMultiSelectModeTest : EditorPresentationTestSetup() { ), styleBackgroundToolbar = ControlPanelState.Toolbar.Styling.Background( isVisible = true, - selectedBackground = ThemeColor.DEFAULT.title + state = StyleToolbarState.Background(background = ThemeColor.DEFAULT.title) ) ) diff --git a/presentation/src/test/java/com/anytypeio/anytype/presentation/editor/editor/EditorScrollAndMoveTest.kt b/presentation/src/test/java/com/anytypeio/anytype/presentation/editor/editor/EditorScrollAndMoveTest.kt index 3e570277f0..e85804dc0a 100644 --- a/presentation/src/test/java/com/anytypeio/anytype/presentation/editor/editor/EditorScrollAndMoveTest.kt +++ b/presentation/src/test/java/com/anytypeio/anytype/presentation/editor/editor/EditorScrollAndMoveTest.kt @@ -124,27 +124,11 @@ class EditorScrollAndMoveTest : EditorPresentationTestSetup() { vm.controlPanelViewState.test().apply { assertValue( ControlPanelState( - navigationToolbar = ControlPanelState.Toolbar.Navigation( - isVisible = false - ), - mainToolbar = ControlPanelState.Toolbar.Main( - isVisible = false - ), - styleTextToolbar = ControlPanelState.Toolbar.Styling( - isVisible = false - ), multiSelect = ControlPanelState.Toolbar.MultiSelect( isVisible = true, isScrollAndMoveEnabled = true, count = 1 - ), - mentionToolbar = ControlPanelState.Toolbar.MentionToolbar( - isVisible = false, - cursorCoordinate = null, - mentionFilter = null, - mentionFrom = null - ), - slashWidget = ControlPanelState.Toolbar.SlashWidget.reset() + ) ) ) } @@ -218,27 +202,11 @@ class EditorScrollAndMoveTest : EditorPresentationTestSetup() { vm.controlPanelViewState.test().apply { assertValue( ControlPanelState( - navigationToolbar = ControlPanelState.Toolbar.Navigation( - isVisible = false - ), - mainToolbar = ControlPanelState.Toolbar.Main( - isVisible = false - ), - styleTextToolbar = ControlPanelState.Toolbar.Styling( - isVisible = false - ), multiSelect = ControlPanelState.Toolbar.MultiSelect( isVisible = true, isScrollAndMoveEnabled = false, count = 1 - ), - mentionToolbar = ControlPanelState.Toolbar.MentionToolbar( - isVisible = false, - cursorCoordinate = null, - mentionFilter = null, - mentionFrom = null - ), - slashWidget = ControlPanelState.Toolbar.SlashWidget.reset() + ) ) ) } @@ -294,26 +262,7 @@ class EditorScrollAndMoveTest : EditorPresentationTestSetup() { ControlPanelState( navigationToolbar = ControlPanelState.Toolbar.Navigation( isVisible = true - ), - mainToolbar = ControlPanelState.Toolbar.Main( - isVisible = false - ), - styleTextToolbar = ControlPanelState.Toolbar.Styling( - isVisible = false - ), - multiSelect = ControlPanelState.Toolbar.MultiSelect( - isVisible = false, - isScrollAndMoveEnabled = false, - isQuickScrollAndMoveMode = false, - count = 0 - ), - mentionToolbar = ControlPanelState.Toolbar.MentionToolbar( - isVisible = false, - cursorCoordinate = null, - mentionFilter = null, - mentionFrom = null - ), - slashWidget = ControlPanelState.Toolbar.SlashWidget.reset() + ) ) ) } @@ -412,25 +361,7 @@ class EditorScrollAndMoveTest : EditorPresentationTestSetup() { ControlPanelState( navigationToolbar = ControlPanelState.Toolbar.Navigation( isVisible = true - ), - mainToolbar = ControlPanelState.Toolbar.Main( - isVisible = false - ), - styleTextToolbar = ControlPanelState.Toolbar.Styling( - isVisible = false - ), - multiSelect = ControlPanelState.Toolbar.MultiSelect( - isVisible = false, - isScrollAndMoveEnabled = false, - count = 0 - ), - mentionToolbar = ControlPanelState.Toolbar.MentionToolbar( - isVisible = false, - cursorCoordinate = null, - mentionFilter = null, - mentionFrom = null - ), - slashWidget = ControlPanelState.Toolbar.SlashWidget.reset() + ) ) ) } diff --git a/presentation/src/test/java/com/anytypeio/anytype/presentation/editor/editor/StyleConfigKtTest.kt b/presentation/src/test/java/com/anytypeio/anytype/presentation/editor/editor/StyleConfigKtTest.kt deleted file mode 100644 index cc78cecfcd..0000000000 --- a/presentation/src/test/java/com/anytypeio/anytype/presentation/editor/editor/StyleConfigKtTest.kt +++ /dev/null @@ -1,1125 +0,0 @@ -package com.anytypeio.anytype.presentation.editor.editor - -import com.anytypeio.anytype.core_models.Block -import com.anytypeio.anytype.presentation.editor.editor.model.Alignment -import com.anytypeio.anytype.presentation.editor.editor.styling.StyleConfig -import com.anytypeio.anytype.presentation.editor.editor.styling.StylingType -import com.anytypeio.anytype.presentation.editor.editor.styling.getStyleConfig -import com.anytypeio.anytype.test_utils.MockDataFactory -import org.junit.Assert.assertEquals -import org.junit.Test - -class StyleConfigKtTest { - - @Test - fun `should return empty style config when block is divider`() { - - val child = MockDataFactory.randomUuid() - - val given = Block( - id = child, - fields = Block.Fields(emptyMap()), - content = Block.Content.Divider(style = Block.Content.Divider.Style.LINE), - children = emptyList() - ) - val result = given.getStyleConfig(focus = null, selection = null) - - val expected = StyleConfig( - visibleTypes = listOf(), - enabledMarkup = listOf(), - enabledAlignment = listOf() - ) - - assertEquals(expected, result) - } - - @Test - fun `should return empty style config when block is page`() { - - val child = MockDataFactory.randomUuid() - - val given = Block( - id = child, - fields = Block.Fields(emptyMap()), - content = Block.Content.Page(style = Block.Content.Page.Style.EMPTY), - children = emptyList() - ) - - val result = given.getStyleConfig(focus = null, selection = null) - - val expected = StyleConfig( - visibleTypes = listOf(), - enabledMarkup = listOf(), - enabledAlignment = listOf() - ) - - assertEquals(expected, result) - } - - @Test - fun `should return empty style config when block is smart`() { - - val child = MockDataFactory.randomUuid() - - val given = Block( - id = child, - fields = Block.Fields(emptyMap()), - content = Block.Content.Smart(), - children = emptyList() - ) - - val result = given.getStyleConfig(focus = null, selection = null) - - val expected = StyleConfig( - visibleTypes = listOf(), - enabledMarkup = listOf(), - enabledAlignment = listOf() - ) - - assertEquals(expected, result) - } - - @Test - fun `should return empty style config when block is icon`() { - - val child = MockDataFactory.randomUuid() - - val given = Block( - id = child, - fields = Block.Fields(emptyMap()), - content = Block.Content.Icon(name = MockDataFactory.randomString()), - children = emptyList() - ) - - val result = given.getStyleConfig(focus = null, selection = null) - - val expected = StyleConfig( - visibleTypes = listOf(), - enabledMarkup = listOf(), - enabledAlignment = listOf() - ) - - assertEquals(expected, result) - } - - @Test - fun `should return empty style config when block is layout`() { - - val child = MockDataFactory.randomUuid() - - val given = Block( - id = child, - fields = Block.Fields(emptyMap()), - content = Block.Content.Layout(type = Block.Content.Layout.Type.DIV), - children = emptyList() - ) - - val result = given.getStyleConfig(focus = null, selection = null) - - val expected = StyleConfig( - visibleTypes = listOf(), - enabledMarkup = listOf(), - enabledAlignment = listOf() - ) - - assertEquals(expected, result) - } - - @Test - fun `should return style with background config when block is link`() { - - val child = MockDataFactory.randomUuid() - - val given = Block( - id = child, - fields = Block.Fields(emptyMap()), - content = Block.Content.Link( - type = Block.Content.Link.Type.PAGE, - target = MockDataFactory.randomUuid(), - fields = Block.Fields.empty() - ), - children = emptyList() - ) - - val result = given.getStyleConfig(focus = null, selection = null) - - val expected = StyleConfig( - visibleTypes = listOf(StylingType.BACKGROUND), - enabledMarkup = listOf(), - enabledAlignment = listOf() - ) - - assertEquals(expected, result) - } - - @Test(expected = IllegalStateException::class) - fun `should return exception when block type bookmark and focus true`() { - - val child = MockDataFactory.randomUuid() - - val given = Block( - id = child, - fields = Block.Fields(emptyMap()), - content = Block.Content.Bookmark( - null, null, null, - null, null - ), - children = emptyList() - ) - - given.getStyleConfig(focus = false, selection = null) - } - - @Test(expected = IllegalStateException::class) - fun `should return exception when block type bookmark and focus false`() { - - val child = MockDataFactory.randomUuid() - - val given = Block( - id = child, - fields = Block.Fields(emptyMap()), - content = Block.Content.Bookmark( - null, null, null, - null, null - ), - children = emptyList() - ) - - given.getStyleConfig(focus = false, selection = null) - } - - @Test - fun `should return empty config when block type bookmark and focus null`() { - - val child = MockDataFactory.randomUuid() - - val given = Block( - id = child, - fields = Block.Fields(emptyMap()), - content = Block.Content.Bookmark( - null, null, null, - null, null - ), - children = emptyList() - ) - - val result = given.getStyleConfig(focus = null, selection = null) - - val expected = StyleConfig.emptyState() - assertEquals(expected, result) - } - - @Test(expected = IllegalStateException::class) - fun `should return exception when block type file and focus true`() { - - val child = MockDataFactory.randomUuid() - - val given = Block( - id = child, - fields = Block.Fields(emptyMap()), - content = Block.Content.File( - type = Block.Content.File.Type.FILE - ), - children = emptyList() - ) - - given.getStyleConfig(focus = false, selection = null) - } - - @Test(expected = IllegalStateException::class) - fun `should return exception when block type file and focus false`() { - - val child = MockDataFactory.randomUuid() - - val given = Block( - id = child, - fields = Block.Fields(emptyMap()), - content = Block.Content.File( - type = Block.Content.File.Type.FILE - ), - children = emptyList() - ) - - given.getStyleConfig(focus = false, selection = null) - } - - @Test - fun `should return style config with background and no align when block type file`() { - - val child = MockDataFactory.randomUuid() - - val given = Block( - id = child, - fields = Block.Fields(emptyMap()), - content = Block.Content.File( - type = Block.Content.File.Type.FILE - ), - children = emptyList() - ) - - val result = given.getStyleConfig(focus = null, selection = null) - - val expected = StyleConfig( - visibleTypes = listOf(StylingType.BACKGROUND), - enabledMarkup = listOf(), - enabledAlignment = listOf() - ) - - assertEquals(expected, result) - } - - @Test - fun `should return style config with background and align when block type image`() { - - val child = MockDataFactory.randomUuid() - - val given = Block( - id = child, - fields = Block.Fields(emptyMap()), - content = Block.Content.File( - type = Block.Content.File.Type.IMAGE - ), - children = emptyList() - ) - - val result = given.getStyleConfig(focus = null, selection = null) - - val expected = StyleConfig( - visibleTypes = listOf(StylingType.BACKGROUND), - enabledMarkup = listOf(), - enabledAlignment = listOf() - ) - - assertEquals(expected, result) - } - - @Test - fun `should return style config with background and align when block type video`() { - - val child = MockDataFactory.randomUuid() - - val given = Block( - id = child, - fields = Block.Fields(emptyMap()), - content = Block.Content.File( - type = Block.Content.File.Type.VIDEO - ), - children = emptyList() - ) - - - val result = given.getStyleConfig(focus = null, selection = null) - - val expected = StyleConfig( - visibleTypes = listOf(StylingType.BACKGROUND), - enabledMarkup = listOf(), - enabledAlignment = listOf() - ) - - assertEquals(expected, result) - } - - @Test - fun `should return empty style config when block type bookmark`() { - - val child = MockDataFactory.randomUuid() - - val given = Block( - id = child, - fields = Block.Fields(emptyMap()), - content = Block.Content.Bookmark( - null, null, null, - null, null - ), - children = emptyList() - ) - - val result = given.getStyleConfig(focus = null, selection = null) - - val expected = StyleConfig( - visibleTypes = listOf(), - enabledMarkup = listOf(), - enabledAlignment = listOf() - ) - - assertEquals(expected, result) - } - - @Test - fun `should return style config when block type text and focus null`() { - - val child = MockDataFactory.randomUuid() - - val given = Block( - id = child, - fields = Block.Fields(emptyMap()), - content = Block.Content.Text( - style = Block.Content.Text.Style.P, - marks = listOf(), - text = "test", - isChecked = null, - color = null, - align = null - ), - backgroundColor = null, - children = emptyList() - ) - - val result = given.getStyleConfig(focus = null, selection = null) - - val expected = StyleConfig( - visibleTypes = listOf(StylingType.STYLE, StylingType.TEXT_COLOR, StylingType.BACKGROUND), - enabledMarkup = listOf( - Markup.Type.BOLD, - Markup.Type.ITALIC, - Markup.Type.STRIKETHROUGH, - Markup.Type.KEYBOARD, - Markup.Type.LINK - ), - enabledAlignment = listOf(Alignment.START, Alignment.CENTER, Alignment.END) - ) - - assertEquals(expected, result) - } - - @Test - fun `should return style config when block type code`() { - - val child = MockDataFactory.randomUuid() - - val given = Block( - id = child, - fields = Block.Fields(emptyMap()), - content = Block.Content.Text( - style = Block.Content.Text.Style.CODE_SNIPPET, - marks = listOf(), - text = "test", - isChecked = null, - color = null, - align = null - ), - backgroundColor = null, - children = emptyList() - ) - - val result = given.getStyleConfig(focus = false, selection = null) - - val expected = StyleConfig( - visibleTypes = listOf(StylingType.BACKGROUND), - enabledMarkup = listOf(), - enabledAlignment = listOf() - ) - - assertEquals(expected, result) - } - - @Test - fun `should return style config when block type paragraph and focus false`() { - - val child = MockDataFactory.randomUuid() - - val given = Block( - id = child, - fields = Block.Fields(emptyMap()), - content = Block.Content.Text( - style = Block.Content.Text.Style.P, - marks = listOf(), - text = "test", - isChecked = null, - color = null, - align = null - ), - backgroundColor = null, - children = emptyList() - ) - - val result = given.getStyleConfig(focus = false, selection = null) - - val expected = StyleConfig( - visibleTypes = listOf(StylingType.STYLE, StylingType.TEXT_COLOR, StylingType.BACKGROUND), - enabledMarkup = listOf( - Markup.Type.BOLD, - Markup.Type.ITALIC, - Markup.Type.STRIKETHROUGH, - Markup.Type.KEYBOARD, - Markup.Type.LINK - ), - enabledAlignment = listOf(Alignment.START, Alignment.CENTER, Alignment.END) - ) - - assertEquals(expected, result) - } - - @Test - fun `should return style config when block type paragraph and range is 0`() { - - val child = MockDataFactory.randomUuid() - - val given = Block( - id = child, - fields = Block.Fields(emptyMap()), - content = Block.Content.Text( - style = Block.Content.Text.Style.P, - marks = listOf(), - text = "test", - isChecked = null, - color = null, - align = null - ), - backgroundColor = null, - children = emptyList() - ) - - val result = given.getStyleConfig(focus = true, selection = IntRange(11, 11)) - - val expected = StyleConfig( - visibleTypes = listOf(StylingType.STYLE, StylingType.TEXT_COLOR, StylingType.BACKGROUND), - enabledMarkup = listOf( - Markup.Type.BOLD, - Markup.Type.ITALIC, - Markup.Type.STRIKETHROUGH, - Markup.Type.KEYBOARD, - Markup.Type.LINK - ), - enabledAlignment = listOf(Alignment.START, Alignment.CENTER, Alignment.END) - ) - - assertEquals(expected, result) - } - - @Test - fun `should return style config when block type paragraph and range is IntRange EMPTY`() { - - val child = MockDataFactory.randomUuid() - - val given = Block( - id = child, - fields = Block.Fields(emptyMap()), - content = Block.Content.Text( - style = Block.Content.Text.Style.P, - marks = listOf(), - text = "test", - isChecked = null, - color = null, - align = null - ), - backgroundColor = null, - children = emptyList() - ) - - val result = given.getStyleConfig(focus = true, selection = IntRange.EMPTY) - - val expected = StyleConfig( - visibleTypes = listOf(StylingType.STYLE, StylingType.TEXT_COLOR, StylingType.BACKGROUND), - enabledMarkup = listOf( - Markup.Type.BOLD, - Markup.Type.ITALIC, - Markup.Type.STRIKETHROUGH, - Markup.Type.KEYBOARD, - Markup.Type.LINK - ), - enabledAlignment = listOf(Alignment.START, Alignment.CENTER, Alignment.END) - ) - - assertEquals(expected, result) - } - - @Test - fun `should return style config when block type paragraph and range first bigger then last`() { - - val child = MockDataFactory.randomUuid() - - val given = Block( - id = child, - fields = Block.Fields(emptyMap()), - content = Block.Content.Text( - style = Block.Content.Text.Style.P, - marks = listOf(), - text = "test", - isChecked = null, - color = null, - align = null - ), - backgroundColor = null, - children = emptyList() - ) - - val result = given.getStyleConfig(focus = true, selection = IntRange(10, 1)) - - val expected = StyleConfig( - visibleTypes = listOf(StylingType.STYLE, StylingType.TEXT_COLOR, StylingType.BACKGROUND), - enabledMarkup = listOf( - Markup.Type.BOLD, - Markup.Type.ITALIC, - Markup.Type.STRIKETHROUGH, - Markup.Type.KEYBOARD, - Markup.Type.LINK - ), - enabledAlignment = listOf(Alignment.START, Alignment.CENTER, Alignment.END) - ) - - assertEquals(expected, result) - } - - @Test - fun `should return style config when block type paragraph and range is not 0`() { - - val child = MockDataFactory.randomUuid() - - val given = Block( - id = child, - fields = Block.Fields(emptyMap()), - content = Block.Content.Text( - style = Block.Content.Text.Style.P, - marks = listOf(), - text = "test", - isChecked = null, - color = null, - align = null - ), - backgroundColor = null, - children = emptyList() - ) - - val result = given.getStyleConfig(focus = true, selection = IntRange(11, 12)) - - val expected = StyleConfig( - visibleTypes = listOf(StylingType.STYLE, StylingType.TEXT_COLOR, StylingType.BACKGROUND), - enabledMarkup = listOf( - Markup.Type.BOLD, - Markup.Type.ITALIC, - Markup.Type.STRIKETHROUGH, - Markup.Type.KEYBOARD, - Markup.Type.LINK - ), - enabledAlignment = emptyList() - ) - - assertEquals(expected, result) - } - - @Test - fun `should return style config when block type header and focus false`() { - - val child = MockDataFactory.randomUuid() - - val given = Block( - id = child, - fields = Block.Fields(emptyMap()), - content = Block.Content.Text( - style = Block.Content.Text.Style.H1, - marks = listOf(), - text = "test", - isChecked = null, - color = null, - align = null - ), - backgroundColor = null, - children = emptyList() - ) - - val result = given.getStyleConfig(focus = false, selection = null) - - val expected = StyleConfig( - visibleTypes = listOf(StylingType.STYLE, StylingType.TEXT_COLOR, StylingType.BACKGROUND), - enabledMarkup = listOf( - Markup.Type.ITALIC, - Markup.Type.STRIKETHROUGH, - Markup.Type.KEYBOARD, - Markup.Type.LINK - ), - enabledAlignment = listOf(Alignment.START, Alignment.CENTER, Alignment.END) - ) - - assertEquals(expected, result) - } - - @Test - fun `should return style config when block type header and range is 0`() { - - val child = MockDataFactory.randomUuid() - - val given = Block( - id = child, - fields = Block.Fields(emptyMap()), - content = Block.Content.Text( - style = Block.Content.Text.Style.H1, - marks = listOf(), - text = "test", - isChecked = null, - color = null, - align = null - ), - backgroundColor = null, - children = emptyList() - ) - - val result = given.getStyleConfig(focus = true, selection = IntRange(11, 11)) - - val expected = StyleConfig( - visibleTypes = listOf(StylingType.STYLE, StylingType.TEXT_COLOR, StylingType.BACKGROUND), - enabledMarkup = listOf( - Markup.Type.ITALIC, - Markup.Type.STRIKETHROUGH, - Markup.Type.KEYBOARD, - Markup.Type.LINK - ), - enabledAlignment = listOf(Alignment.START, Alignment.CENTER, Alignment.END) - ) - - assertEquals(expected, result) - } - - @Test - fun `should return style config when block type header and range is not 0`() { - - val child = MockDataFactory.randomUuid() - - val given = Block( - id = child, - fields = Block.Fields(emptyMap()), - content = Block.Content.Text( - style = Block.Content.Text.Style.H1, - marks = listOf(), - text = "test", - isChecked = null, - color = null, - align = null - ), - backgroundColor = null, - children = emptyList() - ) - - val result = given.getStyleConfig(focus = true, selection = IntRange(11, 12)) - - val expected = StyleConfig( - visibleTypes = listOf(StylingType.STYLE, StylingType.TEXT_COLOR, StylingType.BACKGROUND), - enabledMarkup = listOf( - Markup.Type.ITALIC, - Markup.Type.STRIKETHROUGH, - Markup.Type.KEYBOARD, - Markup.Type.LINK - ), - enabledAlignment = emptyList() - ) - - assertEquals(expected, result) - } - - @Test - fun `should return style config when block type bullet and focus false`() { - - val child = MockDataFactory.randomUuid() - - val given = Block( - id = child, - fields = Block.Fields(emptyMap()), - content = Block.Content.Text( - style = Block.Content.Text.Style.BULLET, - marks = listOf(), - text = "test", - isChecked = null, - color = null, - align = null - ), - backgroundColor = null, - children = emptyList() - ) - - val result = given.getStyleConfig(focus = false, selection = null) - - val expected = StyleConfig( - visibleTypes = listOf(StylingType.STYLE, StylingType.TEXT_COLOR, StylingType.BACKGROUND), - enabledMarkup = listOf( - Markup.Type.BOLD, - Markup.Type.ITALIC, - Markup.Type.STRIKETHROUGH, - Markup.Type.KEYBOARD, - Markup.Type.LINK - ), - enabledAlignment = listOf() - ) - - assertEquals(expected, result) - } - - @Test - fun `should return style config when block type bullet and range is 0`() { - - val child = MockDataFactory.randomUuid() - - val given = Block( - id = child, - fields = Block.Fields(emptyMap()), - content = Block.Content.Text( - style = Block.Content.Text.Style.BULLET, - marks = listOf(), - text = "test", - isChecked = null, - color = null, - align = null - ), - backgroundColor = null, - children = emptyList() - ) - - val result = given.getStyleConfig(focus = true, selection = IntRange(11, 11)) - - val expected = StyleConfig( - visibleTypes = listOf(StylingType.STYLE, StylingType.TEXT_COLOR, StylingType.BACKGROUND), - enabledMarkup = listOf( - Markup.Type.BOLD, - Markup.Type.ITALIC, - Markup.Type.STRIKETHROUGH, - Markup.Type.KEYBOARD, - Markup.Type.LINK - ), - enabledAlignment = listOf() - ) - - assertEquals(expected, result) - } - - @Test - fun `should return style config when block type bullet and range is not 0`() { - - val child = MockDataFactory.randomUuid() - - val given = Block( - id = child, - fields = Block.Fields(emptyMap()), - content = Block.Content.Text( - style = Block.Content.Text.Style.BULLET, - marks = listOf(), - text = "test", - isChecked = null, - color = null, - align = null - ), - backgroundColor = null, - children = emptyList() - ) - - val result = given.getStyleConfig(focus = true, selection = IntRange(11, 12)) - - val expected = StyleConfig( - visibleTypes = listOf(StylingType.STYLE, StylingType.TEXT_COLOR, StylingType.BACKGROUND), - enabledMarkup = listOf( - Markup.Type.BOLD, - Markup.Type.ITALIC, - Markup.Type.STRIKETHROUGH, - Markup.Type.KEYBOARD, - Markup.Type.LINK - ), - enabledAlignment = emptyList() - ) - - assertEquals(expected, result) - } - - @Test - fun `should return style config when block type title and focus false`() { - - val child = MockDataFactory.randomUuid() - - val given = Block( - id = child, - fields = Block.Fields(emptyMap()), - content = Block.Content.Text( - style = Block.Content.Text.Style.TITLE, - marks = listOf(), - text = "test", - isChecked = null, - color = null, - align = null - ), - backgroundColor = null, - children = emptyList() - ) - - val result = given.getStyleConfig(focus = false, selection = null) - - val expected = StyleConfig( - visibleTypes = listOf(StylingType.BACKGROUND), - enabledMarkup = emptyList(), - enabledAlignment = listOf(Alignment.START, Alignment.CENTER, Alignment.END) - ) - - assertEquals(expected, result) - } - - @Test - fun `should return style config when block type title and range is 0`() { - - val child = MockDataFactory.randomUuid() - - val given = Block( - id = child, - fields = Block.Fields(emptyMap()), - content = Block.Content.Text( - style = Block.Content.Text.Style.TITLE, - marks = listOf(), - text = "test", - isChecked = null, - color = null, - align = null - ), - backgroundColor = null, - children = emptyList() - ) - - val result = given.getStyleConfig(focus = true, selection = IntRange(11, 11)) - - val expected = StyleConfig( - visibleTypes = listOf(StylingType.BACKGROUND), - enabledMarkup = emptyList(), - enabledAlignment = listOf(Alignment.START, Alignment.CENTER, Alignment.END) - ) - assertEquals(expected, result) - } - - @Test - fun `should return style config when block type title and range is not 0`() { - - val child = MockDataFactory.randomUuid() - - val given = Block( - id = child, - fields = Block.Fields(emptyMap()), - content = Block.Content.Text( - style = Block.Content.Text.Style.TITLE, - marks = listOf(), - text = "test", - isChecked = null, - color = null, - align = null - ), - backgroundColor = null, - children = emptyList() - ) - - val result = given.getStyleConfig(focus = true, selection = IntRange(11, 12)) - - val expected = StyleConfig( - visibleTypes = listOf(StylingType.BACKGROUND), - enabledMarkup = emptyList(), - enabledAlignment = emptyList() - ) - - assertEquals(expected, result) - } - - @Test - fun `should return style config when block type quote and focus false`() { - - val child = MockDataFactory.randomUuid() - - val given = Block( - id = child, - fields = Block.Fields(emptyMap()), - content = Block.Content.Text( - style = Block.Content.Text.Style.QUOTE, - marks = listOf(), - text = "test", - isChecked = null, - color = null, - align = null - ), - backgroundColor = null, - children = emptyList() - ) - - val result = given.getStyleConfig(focus = false, selection = null) - - val expected = StyleConfig( - visibleTypes = listOf( - StylingType.STYLE, - StylingType.TEXT_COLOR, - StylingType.BACKGROUND - ), - enabledMarkup = listOf( - Markup.Type.BOLD, - Markup.Type.ITALIC, - Markup.Type.STRIKETHROUGH, - Markup.Type.KEYBOARD, - Markup.Type.LINK - ), - enabledAlignment = listOf(Alignment.START, Alignment.END) - ) - - assertEquals(expected, result) - } - - @Test - fun `should return style config when block type qoute and range is 0`() { - - val child = MockDataFactory.randomUuid() - - val given = Block( - id = child, - fields = Block.Fields(emptyMap()), - content = Block.Content.Text( - style = Block.Content.Text.Style.QUOTE, - marks = listOf(), - text = "test", - isChecked = null, - color = null, - align = null - ), - backgroundColor = null, - children = emptyList() - ) - - val result = given.getStyleConfig(focus = true, selection = IntRange(11, 11)) - - val expected = StyleConfig( - visibleTypes = listOf( - StylingType.STYLE, - StylingType.TEXT_COLOR, - StylingType.BACKGROUND - ), - enabledMarkup = listOf( - Markup.Type.BOLD, - Markup.Type.ITALIC, - Markup.Type.STRIKETHROUGH, - Markup.Type.KEYBOARD, - Markup.Type.LINK - ), - enabledAlignment = listOf(Alignment.START, Alignment.END) - ) - assertEquals(expected, result) - } - - @Test - fun `should return style config when block type qoute and range is not 0`() { - - val child = MockDataFactory.randomUuid() - - val given = Block( - id = child, - fields = Block.Fields(emptyMap()), - content = Block.Content.Text( - style = Block.Content.Text.Style.QUOTE, - marks = listOf(), - text = "test", - isChecked = null, - color = null, - align = null - ), - backgroundColor = null, - children = emptyList() - ) - - val result = given.getStyleConfig(focus = true, selection = IntRange(11, 12)) - - val expected = StyleConfig( - visibleTypes = listOf( - StylingType.STYLE, - StylingType.TEXT_COLOR, - StylingType.BACKGROUND - ), - enabledMarkup = listOf( - Markup.Type.BOLD, - Markup.Type.ITALIC, - Markup.Type.STRIKETHROUGH, - Markup.Type.KEYBOARD, - Markup.Type.LINK - ), - enabledAlignment = listOf() - ) - - assertEquals(expected, result) - } - - @Test - fun `should return style config when block type code and focus false`() { - - val child = MockDataFactory.randomUuid() - - val given = Block( - id = child, - fields = Block.Fields(emptyMap()), - content = Block.Content.Text( - style = Block.Content.Text.Style.CODE_SNIPPET, - marks = listOf(), - text = "test", - isChecked = null, - color = null, - align = null - ), - backgroundColor = null, - children = emptyList() - ) - - val result = given.getStyleConfig(focus = false, selection = null) - - val expected = StyleConfig( - visibleTypes = listOf(StylingType.BACKGROUND), - enabledMarkup = listOf(), - enabledAlignment = listOf() - ) - - assertEquals(expected, result) - } - - @Test - fun `should return style config when block type code and range is 0`() { - - val child = MockDataFactory.randomUuid() - - val given = Block( - id = child, - fields = Block.Fields(emptyMap()), - content = Block.Content.Text( - style = Block.Content.Text.Style.CODE_SNIPPET, - marks = listOf(), - text = "test", - isChecked = null, - color = null, - align = null - ), - backgroundColor = null, - children = emptyList() - ) - - val result = given.getStyleConfig(focus = true, selection = IntRange(11, 11)) - - val expected = StyleConfig( - visibleTypes = listOf(StylingType.BACKGROUND), - enabledMarkup = listOf(), - enabledAlignment = listOf() - ) - assertEquals(expected, result) - } - - @Test - fun `should return style config when block type code and range is not 0`() { - - val child = MockDataFactory.randomUuid() - - val given = Block( - id = child, - fields = Block.Fields(emptyMap()), - content = Block.Content.Text( - style = Block.Content.Text.Style.CODE_SNIPPET, - marks = listOf(), - text = "test", - isChecked = null, - color = null, - align = null - ), - backgroundColor = null, - children = emptyList() - ) - - val result = given.getStyleConfig(focus = true, selection = IntRange(11, 12)) - - val expected = StyleConfig( - visibleTypes = listOf(), - enabledMarkup = listOf(), - enabledAlignment = listOf() - ) - - assertEquals(expected, result) - } -} \ No newline at end of file diff --git a/presentation/src/test/java/com/anytypeio/anytype/presentation/editor/editor/styling/StyleToolbarExtKtTest.kt b/presentation/src/test/java/com/anytypeio/anytype/presentation/editor/editor/styling/StyleToolbarExtKtTest.kt new file mode 100644 index 0000000000..800f99fea8 --- /dev/null +++ b/presentation/src/test/java/com/anytypeio/anytype/presentation/editor/editor/styling/StyleToolbarExtKtTest.kt @@ -0,0 +1,116 @@ +package com.anytypeio.anytype.presentation.editor.editor.styling + +import com.anytypeio.anytype.core_models.Block +import com.anytypeio.anytype.core_models.TextStyle +import com.anytypeio.anytype.test_utils.MockDataFactory +import org.junit.Assert +import org.junit.Test + +class StyleToolbarExtKtTest { + + @Test + fun `should return style text state with nullable selected style`() { + + val child = MockDataFactory.randomUuid() + + val given1 = Block( + id = child, + fields = Block.Fields(emptyMap()), + content = Block.Content.Text( + style = Block.Content.Text.Style.P, + text = MockDataFactory.randomString(), + marks = listOf() + ), + backgroundColor = null, + children = emptyList() + ) + + val given2 = Block( + id = child, + fields = Block.Fields(emptyMap()), + content = Block.Content.Text( + style = Block.Content.Text.Style.NUMBERED, + text = MockDataFactory.randomString(), + marks = listOf() + ), + backgroundColor = null, + children = emptyList() + ) + + val given3 = Block( + id = child, + fields = Block.Fields(emptyMap()), + content = Block.Content.Text( + style = Block.Content.Text.Style.P, + text = MockDataFactory.randomString(), + marks = listOf() + ), + backgroundColor = null, + children = emptyList() + ) + + val result = + listOf(given1, given2, given3) + .map { it.content.asText() } + .getStyleTextToolbarState() + + val expected = StyleToolbarState.Text( + textStyle = null + ) + + Assert.assertEquals(expected, result) + } + + @Test + fun `should return style text state with bullet selected style`() { + + val child = MockDataFactory.randomUuid() + + val given1 = Block( + id = child, + fields = Block.Fields(emptyMap()), + content = Block.Content.Text( + style = Block.Content.Text.Style.BULLET, + text = MockDataFactory.randomString(), + marks = listOf() + ), + backgroundColor = null, + children = emptyList() + ) + + val given2 = Block( + id = child, + fields = Block.Fields(emptyMap()), + content = Block.Content.Text( + style = Block.Content.Text.Style.BULLET, + text = MockDataFactory.randomString(), + marks = listOf() + ), + backgroundColor = null, + children = emptyList() + ) + + val given3 = Block( + id = child, + fields = Block.Fields(emptyMap()), + content = Block.Content.Text( + style = Block.Content.Text.Style.BULLET, + text = MockDataFactory.randomString(), + marks = listOf() + ), + backgroundColor = null, + children = emptyList() + ) + + val result = + listOf(given1, given2, given3) + .map { it.content.asText() } + .getStyleTextToolbarState() + + val expected = StyleToolbarState.Text( + textStyle = TextStyle.BULLET + ) + + Assert.assertEquals(expected, result) + } +} \ No newline at end of file diff --git a/sample/src/main/java/com/anytypeio/anytype/sample/StyleActivity.kt b/sample/src/main/java/com/anytypeio/anytype/sample/StyleActivity.kt index 12a0cd3d2a..c20d78df9d 100644 --- a/sample/src/main/java/com/anytypeio/anytype/sample/StyleActivity.kt +++ b/sample/src/main/java/com/anytypeio/anytype/sample/StyleActivity.kt @@ -3,10 +3,6 @@ package com.anytypeio.anytype.sample import android.os.Bundle import android.widget.ImageView import androidx.appcompat.app.AppCompatActivity -import com.anytypeio.anytype.presentation.editor.editor.Markup -import com.anytypeio.anytype.presentation.editor.editor.model.Alignment -import com.anytypeio.anytype.presentation.editor.editor.styling.StyleConfig -import com.anytypeio.anytype.presentation.editor.editor.styling.StylingType import kotlinx.android.synthetic.main.activity_style.* class StyleActivity: AppCompatActivity() { @@ -20,38 +16,6 @@ class StyleActivity: AppCompatActivity() { } button.setOnClickListener { - styleToolbar.update( - config = StyleConfig( - visibleTypes = listOf( - StylingType.STYLE, - StylingType.TEXT_COLOR, - StylingType.BACKGROUND - ), - enabledMarkup = listOf( - Markup.Type.BOLD, - Markup.Type.ITALIC, - Markup.Type.STRIKETHROUGH, - Markup.Type.KEYBOARD, - Markup.Type.LINK - ), - enabledAlignment = listOf( - Alignment.START, - Alignment.END - ) - ), - props = com.anytypeio.anytype.presentation.editor.editor.control.ControlPanelState.Toolbar.Styling.Props( - isBold = false, - isItalic = false, - isStrikethrough = true, - isCode = false, - isLinked = false, - color = null, - background = null, - alignment = null - ) - ) - //styleToolbar.showWithAnimation() - } } } \ No newline at end of file