mirror of
https://github.com/anyproto/anytype-kotlin.git
synced 2025-06-08 05:47:05 +09:00
Editor | Fix | Style toolbars refactoring (#2238)
* legacy * added model for style toolbars state * ext fun for getting text style toolbar state + tests * move text style toolbar to use new state * moving the style background toolbar to a new state * update control panel events * update control machine event for background toolbar * code block uses cursor * close kayboard on opening background toolbar * refresh background toolbar * refresh bakground toolbar 2 * send blocks background update command * start background toolbar for code block and style toolbar for others * update style color toolbar * update style color toolbar with state * update style color toolbar vm logic * get style color toolbar state * style other toolbar new state * get style other toolbar state + vm logic * legacy styleconfig model * legacy * on style event click refactoring * on close background toolbar event * added new command, blockList set mark * remove doubles * markup type to core model * legacy * update markup for several text blocks * update style other toolbar with selected states * toolbars viewmodels logic * legacy, code style * code style * fixed tests * test fix Co-authored-by: konstantiniiv <ki@anytype.io>
This commit is contained in:
parent
a2d2189376
commit
2e3e22aacd
26 changed files with 804 additions and 2770 deletions
|
@ -1378,7 +1378,7 @@ open class EditorFragment : NavigationFragment<FragmentEditorBinding>(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<FragmentEditorBinding>(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<FragmentEditorBinding>(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<FragmentEditorBinding>(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 {
|
||||
|
|
|
@ -276,4 +276,9 @@ fun List<Block>.getChildrenIdsList(parent: Id): List<String> {
|
|||
fun List<Block>.isAllTextAndNoneCodeBlocks(): Boolean =
|
||||
all { block ->
|
||||
block.content is Content.Text && block.content.style != Content.Text.Style.CODE_SNIPPET
|
||||
}
|
||||
|
||||
fun List<Block>.isAllTextBlocks(): Boolean =
|
||||
all { block ->
|
||||
block.content is Content.Text
|
||||
}
|
|
@ -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 }
|
||||
|
|
|
@ -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)
|
||||
|
|
|
@ -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
|
||||
}
|
||||
}
|
|
@ -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<StylingType>,
|
||||
private val enabledMarkup: ArrayList<Markup.Type>,
|
||||
private val enabledAlignment: ArrayList<Alignment>,
|
||||
private var state: StyleToolbarState.ColorBackground,
|
||||
private val onStylingEvent: (StylingEvent) -> Unit
|
||||
) : RecyclerView.Adapter<RecyclerView.ViewHolder>() {
|
||||
|
||||
@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)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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
|
||||
}
|
||||
}
|
||||
}
|
|
@ -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<StylingEvent>()
|
||||
|
||||
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)
|
||||
}
|
||||
}
|
|
@ -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<Overlap>()
|
||||
val backgroundOverlaps = mutableListOf<Overlap>()
|
||||
|
||||
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:${
|
||||
|
|
|
@ -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<Id>) {
|
||||
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<Id>) {
|
||||
val selected = blocks.filter { ids.contains(it.id) }
|
||||
val state = selected.getStyleBackgroundToolbarState()
|
||||
controlPanelInteractor.onEvent(
|
||||
ControlPanelMachine.Event.StylingToolbar.OnUpdateBackgroundToolbar(state)
|
||||
)
|
||||
}
|
||||
|
||||
private fun onSendUpdateStyleColorBackgroundToolbarEvent(ids: List<Id>) {
|
||||
val selected = blocks.filter { ids.contains(it.id) }
|
||||
val state = selected.getStyleColorBackgroundToolbarState()
|
||||
controlPanelInteractor.onEvent(
|
||||
ControlPanelMachine.Event.StylingToolbar.OnUpdateColorBackgroundToolbar(state)
|
||||
)
|
||||
}
|
||||
|
||||
private fun onSendUpdateStyleOtherToolbarEvent(ids: List<Id>) {
|
||||
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<BlockView>) {
|
||||
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<Id>? = 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<Id>, 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<Id>, color: String?) {
|
||||
check(color != null)
|
||||
controlPanelInteractor.onEvent(ControlPanelMachine.Event.OnBlockBackgroundColorSelected)
|
||||
private fun onBlockBackgroundColorAction(ids: List<Id>, 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<Content.Text>().text,
|
||||
marks = new.content<Content.Text>().marks
|
||||
private fun onUpdateBlockListMarkup(ids: List<Id>, 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(
|
||||
|
|
|
@ -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())
|
||||
|
|
|
@ -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<Markup.Mark>
|
||||
) {
|
||||
|
||||
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,
|
||||
|
|
|
@ -387,7 +387,12 @@ fun List<BlockView>.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)
|
||||
|
|
|
@ -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
|
||||
}
|
||||
|
||||
|
|
|
@ -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<StylingType>,
|
||||
val enabledMarkup: List<Markup.Type>,
|
||||
val enabledAlignment: List<Alignment>
|
||||
) {
|
||||
|
||||
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<Markup.Type> = 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")
|
||||
}
|
||||
|
|
@ -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<Id>? = 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<Block.Content.Text>.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<Block>.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<Block>.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<Block.Content.Text>.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<Alignment> = 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<Markup.Type> = 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
|
|
@ -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)
|
||||
}
|
||||
}
|
||||
}
|
|
@ -727,20 +727,6 @@ fun ObjectLayoutView.toObjectLayout() = when (this) {
|
|||
is ObjectLayoutView.Todo -> ObjectType.Layout.TODO
|
||||
}
|
||||
|
||||
fun List<Block>.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<Block>.getSelectedBackgroundForSelectedBlocks(): String? {
|
||||
val backgrounds = map { it.backgroundColor ?: ThemeColor.DEFAULT.title }.distinct()
|
||||
return if (backgrounds.size == 1) backgrounds[0] else null
|
||||
}
|
||||
|
||||
fun List<Block>.getTextStyleForSelectedTextBlocks(): Block.Content.Text.Style? {
|
||||
val styles = map { it.textStyle() }.distinct()
|
||||
return if (styles.size == 1) styles[0] else null
|
||||
|
|
|
@ -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
|
||||
)
|
||||
)
|
||||
|
||||
|
|
|
@ -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(
|
||||
|
|
|
@ -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,
|
||||
|
|
|
@ -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)
|
||||
)
|
||||
)
|
||||
|
||||
|
|
|
@ -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()
|
||||
)
|
||||
)
|
||||
)
|
||||
}
|
||||
|
|
File diff suppressed because it is too large
Load diff
|
@ -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)
|
||||
}
|
||||
}
|
|
@ -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()
|
||||
|
||||
}
|
||||
}
|
||||
}
|
Loading…
Add table
Add a link
Reference in a new issue