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

Editor | Styling toolbar | Selected states (#1461)

This commit is contained in:
Evgenii Kozlov 2021-05-12 21:55:07 +03:00 committed by GitHub
parent bfa6205656
commit df705afe6c
Signed by: github
GPG key ID: 4AEE18F83AFDEB23
19 changed files with 158 additions and 105 deletions

View file

@ -1125,6 +1125,7 @@ open class PageFragment :
lifecycleScope.launch {
hideSoftInput()
delay(DEFAULT_ANIM_DURATION)
stylingToolbar.setSelectedStyle(style)
BottomSheetBehavior.from(stylingToolbar).apply {
setState(BottomSheetBehavior.STATE_EXPANDED)
addBottomSheetCallback(onHideBottomSheetCallback)
@ -1140,6 +1141,7 @@ open class PageFragment :
state.styleExtraToolbar.apply {
if (isVisible) {
styleToolbarOther.setProperties(state.stylingToolbar.props)
lifecycleScope.launch {
BottomSheetBehavior.from(styleToolbarOther).apply {
setState(BottomSheetBehavior.STATE_EXPANDED)
@ -1156,6 +1158,12 @@ open class PageFragment :
state.styleColorToolbar.apply {
if (isVisible) {
state.stylingToolbar.config?.let { config ->
styleToolbarColors.update(
config,
state.stylingToolbar.props
)
}
lifecycleScope.launch {
BottomSheetBehavior.from(styleToolbarColors).apply {
setState(BottomSheetBehavior.STATE_EXPANDED)

View file

@ -199,7 +199,7 @@
</FrameLayout>
<com.anytypeio.anytype.core_ui.widgets.StyleToolbarWidgetNew
<com.anytypeio.anytype.core_ui.widgets.StyleToolbarMainWidget
android:id="@+id/stylingToolbar"
android:layout_width="match_parent"
android:layout_height="wrap_content"
@ -210,7 +210,7 @@
app:cardUseCompatPadding="true"
app:layout_behavior="@string/bottom_sheet_behavior" />
<com.anytypeio.anytype.core_ui.widgets.toolbar.StyleToolbarOther
<com.anytypeio.anytype.core_ui.widgets.toolbar.StyleToolbarExtraWidget
android:id="@+id/styleToolbarOther"
android:layout_width="match_parent"
android:layout_height="wrap_content"

View file

@ -6,6 +6,7 @@ typealias Hash = String
typealias Document = List<Block>
typealias TextStyle = Block.Content.Text.Style
typealias CBTextStyle = Block.Content.Text.Style
typealias DV = Block.Content.DataView

View file

@ -0,0 +1,78 @@
package com.anytypeio.anytype.core_ui.widgets
import android.content.Context
import android.util.AttributeSet
import android.view.LayoutInflater
import android.view.View
import android.widget.Toast
import androidx.cardview.widget.CardView
import com.anytypeio.anytype.core_models.TextStyle
import com.anytypeio.anytype.core_ui.R
import com.anytypeio.anytype.core_ui.extensions.toast
import com.anytypeio.anytype.core_ui.reactive.clicks
import com.anytypeio.anytype.presentation.page.editor.model.UiBlock
import kotlinx.android.synthetic.main.widget_style_toolbar_main.view.*
import kotlinx.coroutines.flow.map
import kotlinx.coroutines.flow.merge
class StyleToolbarMainWidget @JvmOverloads constructor(
context: Context,
attrs: AttributeSet? = null
) : CardView(context, attrs) {
init {
LayoutInflater
.from(context)
.inflate(R.layout.widget_style_toolbar_main, this)
callout.setOnClickListener {
context.toast(
msg = "Will be implemented later",
duration = Toast.LENGTH_SHORT
)
}
}
val styles = merge(
tvStyleTitle.clicks().map { UiBlock.HEADER_ONE },
tvStyleHeading.clicks().map { UiBlock.HEADER_TWO },
tvStyleSubheading.clicks().map { UiBlock.HEADER_THREE },
tvStyleText.clicks().map { UiBlock.TEXT },
checkbox.clicks().map { UiBlock.CHECKBOX },
bulleted.clicks().map { UiBlock.BULLETED },
numbered.clicks().map { UiBlock.NUMBERED },
toggle.clicks().map { UiBlock.TOGGLE },
highlight.clicks().map { UiBlock.HIGHLIGHTED },
)
val other = dots.clicks()
val colors = markupColors.clicks()
fun setSelectedStyle(style: TextStyle) {
when (style) {
TextStyle.P -> select(tvStyleText.id)
TextStyle.H1 -> select(tvStyleTitle.id)
TextStyle.H2 -> select(tvStyleHeading.id)
TextStyle.H3 -> select(tvStyleSubheading.id)
TextStyle.H4 -> select(tvStyleSubheading.id)
TextStyle.QUOTE -> select(highlight.id)
TextStyle.BULLET -> select(bulleted.id)
TextStyle.NUMBERED -> select(numbered.id)
TextStyle.TOGGLE -> select(toggle.id)
TextStyle.CHECKBOX -> select(checkbox.id)
else -> select(View.NO_ID)
}
}
private fun select(selectedViewId: Int) {
tvStyleText.apply { isSelected = id == selectedViewId }
tvStyleTitle.apply { isSelected = id == selectedViewId }
tvStyleHeading.apply { isSelected = id == selectedViewId }
tvStyleSubheading.apply { isSelected = id == selectedViewId }
checkbox.apply { isSelected = id == selectedViewId }
bulleted.apply { isSelected = id == selectedViewId }
numbered.apply { isSelected = id == selectedViewId }
toggle.apply { isSelected = id == selectedViewId }
highlight.apply { isSelected = id == selectedViewId }
}
}

View file

@ -1,41 +0,0 @@
package com.anytypeio.anytype.core_ui.widgets
import android.content.Context
import android.util.AttributeSet
import android.view.LayoutInflater
import androidx.cardview.widget.CardView
import com.anytypeio.anytype.core_ui.R
import com.anytypeio.anytype.core_ui.reactive.clicks
import com.anytypeio.anytype.presentation.page.editor.model.UiBlock
import kotlinx.android.synthetic.main.widget_styling_toolbar_main.view.*
import kotlinx.coroutines.flow.flattenMerge
import kotlinx.coroutines.flow.flowOf
import kotlinx.coroutines.flow.map
class StyleToolbarWidgetNew @JvmOverloads constructor(
context: Context,
attrs: AttributeSet? = null
) : CardView(context, attrs) {
init {
LayoutInflater
.from(context)
.inflate(R.layout.widget_styling_toolbar_main, this)
}
val styles = flowOf(
tvStyleTitle.clicks().map { UiBlock.HEADER_ONE },
tvStyleHeading.clicks().map { UiBlock.HEADER_TWO },
tvStyleSubheading.clicks().map { UiBlock.HEADER_THREE },
tvStyleText.clicks().map { UiBlock.TEXT },
checkbox.clicks().map { UiBlock.CHECKBOX },
bulleted.clicks().map { UiBlock.BULLETED },
numbered.clicks().map { UiBlock.NUMBERED },
toggle.clicks().map { UiBlock.TOGGLE },
highlight.clicks().map { UiBlock.HIGHLIGHTED },
).flattenMerge()
val other = dots.clicks()
val colors = markupColors.clicks()
}

View file

@ -6,13 +6,15 @@ import android.view.LayoutInflater
import androidx.cardview.widget.CardView
import com.anytypeio.anytype.core_ui.R
import com.anytypeio.anytype.core_ui.reactive.clicks
import com.anytypeio.anytype.presentation.page.editor.control.ControlPanelState
import com.anytypeio.anytype.presentation.page.editor.model.Alignment
import com.anytypeio.anytype.presentation.page.editor.styling.StylingEvent
import kotlinx.android.synthetic.main.widget_block_style_other.view.*
import kotlinx.android.synthetic.main.widget_block_style_extra.view.*
import kotlinx.coroutines.flow.Flow
import kotlinx.coroutines.flow.map
import kotlinx.coroutines.flow.merge
class StyleToolbarOther @JvmOverloads constructor(
class StyleToolbarExtraWidget @JvmOverloads constructor(
context: Context,
attrs: AttributeSet? = null
) : CardView(context, attrs) {
@ -20,7 +22,7 @@ class StyleToolbarOther @JvmOverloads constructor(
init {
LayoutInflater
.from(context)
.inflate(R.layout.widget_block_style_other, this)
.inflate(R.layout.widget_block_style_extra, this)
}
val actions : Flow<StylingEvent> = merge(
@ -33,4 +35,15 @@ class StyleToolbarOther @JvmOverloads constructor(
alignmentRight.clicks().map { StylingEvent.Alignment.Right },
setUrl.clicks().map { StylingEvent.Markup.Link }
)
fun setProperties(props: ControlPanelState.Toolbar.Styling.Props?) {
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
}
}

View file

@ -6,7 +6,6 @@ import android.view.LayoutInflater
import android.widget.TextView
import androidx.cardview.widget.CardView
import com.anytypeio.anytype.core_ui.R
import com.anytypeio.anytype.core_ui.reactive.clicks
import com.anytypeio.anytype.presentation.page.editor.control.ControlPanelState
import com.anytypeio.anytype.presentation.page.editor.styling.StyleConfig
import com.anytypeio.anytype.presentation.page.editor.styling.StylingEvent
@ -58,6 +57,4 @@ class StyleColorToolbarWidget @JvmOverloads constructor(
blockStyleAdapter.updateConfig(config, props)
blockStyleAdapter.notifyDataSetChanged()
}
fun closeButtonClicks() = close.clicks()
}

View file

@ -3,5 +3,5 @@
<corners
android:bottomLeftRadius="10dp"
android:topLeftRadius="10dp" />
<solid android:color="#FFB522" />
<solid android:color="#1A867D42" />
</shape>

View file

@ -1,4 +1,4 @@
<shape xmlns:android="http://schemas.android.com/apk/res/android"
android:shape="rectangle">
<solid android:color="#FFB522" />
<solid android:color="#1A867D42" />
</shape>

View file

@ -3,5 +3,5 @@
<corners
android:bottomRightRadius="10dp"
android:topRightRadius="10dp" />
<solid android:color="#FFB522" />
<solid android:color="#1A867D42" />
</shape>

View file

@ -109,7 +109,7 @@
<color name="context_menu_selected_item">#ACA996</color>
<color name="default_style_color_circle_outer_stroke_color">#FFB522</color>
<color name="default_style_color_circle_outer_stroke_color">#E4E2D7</color>
<color name="default_style_color_circle_inner_stroke_color">#DFDDD0</color>
<color name="viewer_filter_add_stroke_color">#DFDDD0</color>
<color name="default_tag_text_color">#E89D00</color>

View file

@ -116,7 +116,7 @@
<dimen name="popup_context_menu_height">44dp</dimen>
<dimen name="popup_context_menu_margin">8dp</dimen>
<dimen name="popup_context_menu_bottom_allowance">40dp</dimen>
<dimen name="default_style_color_circle_inner_radius">24dp</dimen>
<dimen name="default_style_color_circle_inner_radius">22dp</dimen>
<dimen name="default_style_color_outer_stroke_width">2dp</dimen>
<dimen name="default_page_links_bottom_offset">64dp</dimen>

View file

@ -1,23 +1,22 @@
# Project-wide Gradle settings.
# IDE (e.g. Android Studio) users:
# Gradle settings configured through the IDE *will override*
# any settings specified in this file.
# For more details on how to configure your build environment visit
## For more details on how to configure your build environment visit
# http://www.gradle.org/docs/current/userguide/build_environment.html
#
# Specifies the JVM arguments used for the daemon process.
# The setting is particularly useful for tweaking memory settings.
org.gradle.jvmargs=-Xmx1536m
# Default value: -Xmx1024m -XX:MaxPermSize=256m
# org.gradle.jvmargs=-Xmx2048m -XX:MaxPermSize=512m -XX:+HeapDumpOnOutOfMemoryError -Dfile.encoding=UTF-8
#
# When configured, Gradle will run in incubating parallel mode.
# This option should only be used with decoupled projects. More details, visit
# http://www.gradle.org/docs/current/userguide/multi_project_builds.html#sec:decoupled_projects
# org.gradle.parallel=true
# AndroidX package structure to make it clearer which packages are bundled with the
# Android operating system, and which are packaged with your app's APK
# https://developer.android.com/topic/libraries/support-library/androidx-rn
android.useAndroidX=true
org.gradle.parallel=true
org.gradle.caching=true
org.gradle.jvmargs=-Xmx2048M
android.enableR8=true
# Automatically convert third-party libraries to use AndroidX
android.enableUnitTestBinaryResources=true
android.useAndroidX=true
android.enableJetifier=false
# Kotlin code style for this project: "official" or "obsolete":
kotlin.code.style=official
android.enableUnitTestBinaryResources=true
kotlin.code.style=official

View file

@ -1,6 +1,7 @@
package com.anytypeio.anytype.presentation.page
import com.anytypeio.anytype.core_models.Block
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.presentation.common.StateReducer
@ -416,6 +417,11 @@ sealed class ControlPanelMachine {
}
is Event.OnBlockActionToolbarStyleClicked -> {
val target = target(event.target)
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
@ -424,6 +430,7 @@ sealed class ControlPanelMachine {
isVisible = true,
mode = getModeForSelection(event.selection),
target = target,
style = style,
config = event.target.getStyleConfig(event.focused, event.selection),
props = getPropsForSelection(target, event.selection)
),
@ -521,41 +528,30 @@ sealed class ControlPanelMachine {
state: ControlPanelState,
event: Event.OnRefresh.StyleToolbar
): ControlPanelState {
return if (state.stylingToolbar.mode == StylingMode.MARKUP) {
if (event.target != null) {
val target = target(event.target)
event.selection?.let {
val props = getMarkupLevelStylingProps(target, it)
state.copy(
stylingToolbar = state.stylingToolbar.copy(
props = props,
target = target
)
val target = event.target?.let { target(it) }
val style = event.target?.let {
val content = it.content
check(content is Block.Content.Text)
content.style
} ?: TextStyle.P
return state.copy(
stylingToolbar = state.stylingToolbar.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
)
} ?: state.copy()
} else {
state.copy()
}
} else {
val target = event.target?.let { target(it) }
state.copy(
stylingToolbar = state.stylingToolbar.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 getModeForSelection(selection: IntRange?): StylingMode {

View file

@ -462,7 +462,7 @@ class PageViewModel(
private fun refreshStyleToolbar(document: Document) {
controlPanelViewState.value?.let { state ->
if (state.stylingToolbar.isVisible) {
if (state.stylingToolbar.isVisible || state.styleColorToolbar.isVisible || state.styleExtraToolbar.isVisible) {
state.stylingToolbar.target?.id?.let { targetId ->
controlPanelInteractor.onEvent(
event = ControlPanelMachine.Event.OnRefresh.StyleToolbar(

View file

@ -1,5 +1,6 @@
package com.anytypeio.anytype.presentation.page.editor.control
import com.anytypeio.anytype.core_models.TextStyle
import com.anytypeio.anytype.presentation.page.editor.Markup
import com.anytypeio.anytype.presentation.page.editor.mention.Mention
import com.anytypeio.anytype.presentation.page.editor.model.Alignment
@ -104,7 +105,8 @@ data class ControlPanelState(
val target: Target? = null,
val config: StyleConfig? = null,
val props: Props? = null,
val mode: StylingMode? = null
val mode: StylingMode? = null,
val style: TextStyle = TextStyle.P
) : Toolbar() {
companion object {

View file

@ -7,7 +7,7 @@
android:layout_height="match_parent"
tools:context=".StyleToolbarActivity">
<com.anytypeio.anytype.core_ui.widgets.StyleToolbarWidgetNew
<com.anytypeio.anytype.core_ui.widgets.StyleToolbarMainWidget
app:cardBackgroundColor="@color/white"
app:cardCornerRadius="16dp"
android:id="@+id/toolbar"