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

Page icon action menu (#536)

This commit is contained in:
Evgenii Kozlov 2020-06-18 20:21:42 +02:00 committed by GitHub
parent 984f0b937c
commit 7a519e660a
Signed by: github
GPG key ID: 4AEE18F83AFDEB23
32 changed files with 692 additions and 466 deletions

View file

@ -5,10 +5,12 @@
### New features 🚀
* Styling toolbar shows currently applied style in markup-styling mode (#525)
* Wired document's icon with action menu (#529)
### Design & UX 🔳
*
* Redesigned page emoji icon picker (#531)
*
### Fixes & tech 🚒

View file

@ -4,7 +4,8 @@ import com.agileburo.anytype.core_utils.di.scope.PerScreen
import com.agileburo.anytype.domain.block.repo.BlockRepository
import com.agileburo.anytype.domain.icon.SetIconName
import com.agileburo.anytype.presentation.page.picker.PageIconPickerViewModelFactory
import com.agileburo.anytype.ui.page.modals.PageIconPickerFragment
import com.agileburo.anytype.ui.page.modals.DocumentEmojiIconPickerFragment
import com.agileburo.anytype.ui.page.modals.actions.DocumentIconActionMenu
import dagger.Module
import dagger.Provides
import dagger.Subcomponent
@ -19,7 +20,8 @@ interface PageIconPickerSubComponent {
fun build(): PageIconPickerSubComponent
}
fun inject(fragment: PageIconPickerFragment)
fun inject(fragment: DocumentEmojiIconPickerFragment)
fun inject(fragment: DocumentIconActionMenu)
}
@Module

View file

@ -20,6 +20,8 @@ import androidx.lifecycle.Observer
import androidx.lifecycle.ViewModelProviders
import androidx.lifecycle.lifecycleScope
import androidx.recyclerview.widget.LinearLayoutManager
import androidx.transition.ChangeBounds
import androidx.transition.Fade
import com.agileburo.anytype.R
import com.agileburo.anytype.core_ui.common.Alignment
import com.agileburo.anytype.core_ui.common.Markup
@ -56,6 +58,7 @@ import com.agileburo.anytype.ui.base.NavigationFragment
import com.agileburo.anytype.ui.menu.AnytypeContextMenu
import com.agileburo.anytype.ui.page.modals.*
import com.agileburo.anytype.ui.page.modals.actions.BlockActionToolbarFactory
import com.agileburo.anytype.ui.page.modals.actions.DocumentIconActionMenu
import com.google.android.material.bottomsheet.BottomSheetBehavior
import com.hbisoft.pickit.PickiT
import com.hbisoft.pickit.PickiTCallbacks
@ -515,8 +518,27 @@ open class PageFragment :
private fun execute(event: EventWrapper<Command>) {
event.getContentIfNotHandled()?.let { command ->
when (command) {
is Command.OpenPagePicker -> {
PageIconPickerFragment.newInstance(
is Command.OpenDocumentIconActionMenu -> {
hideSoftInput()
if (recycler.scrollY > 0) recycler.smoothScrollToPosition(0)
val shared = recycler.getChildAt(0).findViewById<TextView>(R.id.logo)
val fr = DocumentIconActionMenu.new(
y = shared.y + dimen(R.dimen.dp_48),
emoji = shared.text.toString(),
target = command.target
).apply {
enterTransition = Fade()
exitTransition = Fade()
sharedElementEnterTransition = ChangeBounds()
}
childFragmentManager.beginTransaction()
.add(R.id.root, fr)
.addToBackStack(null)
.apply { addSharedElement(shared, getString(R.string.logo_transition)) }
.commit()
}
is Command.OpenDocumentEmojiIconPicker -> {
DocumentEmojiIconPickerFragment.newInstance(
context = requireArguments().getString(ID_KEY, ID_EMPTY_VALUE),
target = command.target
).show(childFragmentManager, null)

View file

@ -15,18 +15,18 @@ import com.agileburo.anytype.R
import com.agileburo.anytype.core_utils.ext.toast
import com.agileburo.anytype.core_utils.ui.BaseBottomSheetFragment
import com.agileburo.anytype.di.common.componentManager
import com.agileburo.anytype.library_page_icon_picker_widget.ui.PageIconPickerAdapter
import com.agileburo.anytype.library_page_icon_picker_widget.ui.PageIconPickerViewHolder
import com.agileburo.anytype.presentation.page.picker.PageIconPickerViewModel
import com.agileburo.anytype.presentation.page.picker.PageIconPickerViewModel.Contract
import com.agileburo.anytype.presentation.page.picker.PageIconPickerViewModel.ViewState
import com.agileburo.anytype.library_page_icon_picker_widget.ui.DocumentEmojiIconPickerAdapter
import com.agileburo.anytype.library_page_icon_picker_widget.ui.DocumentEmojiIconPickerViewHolder
import com.agileburo.anytype.presentation.page.picker.DocumentIconPickerViewModel
import com.agileburo.anytype.presentation.page.picker.DocumentIconPickerViewModel.Contract
import com.agileburo.anytype.presentation.page.picker.DocumentIconPickerViewModel.ViewState
import com.agileburo.anytype.presentation.page.picker.PageIconPickerViewModelFactory
import com.google.android.material.bottomsheet.BottomSheetBehavior
import com.google.android.material.bottomsheet.BottomSheetDialog
import kotlinx.android.synthetic.main.fragment_page_icon_picker.*
import javax.inject.Inject
class PageIconPickerFragment : BaseBottomSheetFragment() {
class DocumentEmojiIconPickerFragment : BaseBottomSheetFragment() {
private val target: String
get() = requireArguments()
@ -44,22 +44,13 @@ class PageIconPickerFragment : BaseBottomSheetFragment() {
private val vm by lazy {
ViewModelProviders
.of(this, factory)
.get(PageIconPickerViewModel::class.java)
.get(DocumentIconPickerViewModel::class.java)
}
private val pageIconPickerAdapter by lazy {
PageIconPickerAdapter(
DocumentEmojiIconPickerAdapter(
views = emptyList(),
onUploadPhotoClicked = { toast(NOT_IMPLEMENTED_MESSAGE) },
onFilterQueryChanged = { vm.onEvent(Contract.Event.OnFilterQueryChanged(it)) },
onSetRandomEmojiClicked = {
vm.onEvent(
Contract.Event.OnSetRandomEmojiClicked(
target = target,
context = context
)
)
},
onEmojiClicked = { unicode, alias ->
vm.onEvent(
Contract.Event.OnEmojiClicked(
@ -100,12 +91,9 @@ class PageIconPickerFragment : BaseBottomSheetFragment() {
spanSizeLookup = object : GridLayoutManager.SpanSizeLookup() {
override fun getSpanSize(position: Int) =
when (val type = pageIconPickerAdapter.getItemViewType(position)) {
PageIconPickerViewHolder.HOLDER_UPLOAD_PHOTO -> PAGE_ICON_PICKER_DEFAULT_SPAN_COUNT
PageIconPickerViewHolder.HOLDER_CHOOSE_EMOJI -> PAGE_ICON_PICKER_DEFAULT_SPAN_COUNT
PageIconPickerViewHolder.HOLDER_PICK_RANDOM_EMOJI -> PAGE_ICON_PICKER_DEFAULT_SPAN_COUNT
PageIconPickerViewHolder.HOLDER_EMOJI_CATEGORY_HEADER -> PAGE_ICON_PICKER_DEFAULT_SPAN_COUNT
PageIconPickerViewHolder.HOLDER_EMOJI_FILTER -> PAGE_ICON_PICKER_DEFAULT_SPAN_COUNT
PageIconPickerViewHolder.HOLDER_EMOJI_ITEM -> 1
DocumentEmojiIconPickerViewHolder.HOLDER_EMOJI_ITEM -> 1
DocumentEmojiIconPickerViewHolder.HOLDER_EMOJI_CATEGORY_HEADER -> PAGE_ICON_PICKER_DEFAULT_SPAN_COUNT
DocumentEmojiIconPickerViewHolder.HOLDER_EMOJI_FILTER -> PAGE_ICON_PICKER_DEFAULT_SPAN_COUNT
else -> throw IllegalStateException("$UNEXPECTED_VIEW_TYPE_MESSAGE: $type")
}
}
@ -114,15 +102,6 @@ class PageIconPickerFragment : BaseBottomSheetFragment() {
setHasStableIds(true)
}
}
remove.setOnClickListener {
vm.onEvent(
Contract.Event.OnRemoveEmojiSelected(
context = context,
target = target
)
)
}
}
override fun onActivityCreated(savedInstanceState: Bundle?) {
@ -171,7 +150,7 @@ class PageIconPickerFragment : BaseBottomSheetFragment() {
fun newInstance(
context: String,
target: String
) = PageIconPickerFragment().apply {
) = DocumentEmojiIconPickerFragment().apply {
arguments = bundleOf(ARG_CONTEXT_ID_KEY to context, ARG_TARGET_ID_KEY to target)
}
@ -181,7 +160,6 @@ class PageIconPickerFragment : BaseBottomSheetFragment() {
private const val ARG_TARGET_ID_KEY = "arg.picker.target.id"
private const val MISSING_TARGET_ERROR = "Missing target id"
private const val MISSING_CONTEXT_ERROR = "Missing context id"
private const val NOT_IMPLEMENTED_MESSAGE = "Not implemented"
private const val UNEXPECTED_VIEW_TYPE_MESSAGE = "Unexpected view type"
}
}

View file

@ -0,0 +1,168 @@
package com.agileburo.anytype.ui.page.modals.actions
import android.os.Bundle
import android.view.View
import android.view.animation.OvershootInterpolator
import androidx.core.os.bundleOf
import androidx.lifecycle.Observer
import androidx.lifecycle.ViewModelProviders
import com.agileburo.anytype.R
import com.agileburo.anytype.core_utils.ext.toast
import com.agileburo.anytype.core_utils.ui.BaseFragment
import com.agileburo.anytype.di.common.componentManager
import com.agileburo.anytype.library_page_icon_picker_widget.ui.ActionMenuAdapter
import com.agileburo.anytype.library_page_icon_picker_widget.ui.ActionMenuAdapter.Companion.OPTION_CHOOSE_EMOJI
import com.agileburo.anytype.library_page_icon_picker_widget.ui.ActionMenuAdapter.Companion.OPTION_CHOOSE_RANDOM_EMOJI
import com.agileburo.anytype.library_page_icon_picker_widget.ui.ActionMenuAdapter.Companion.OPTION_CHOOSE_UPLOAD_PHOTO
import com.agileburo.anytype.library_page_icon_picker_widget.ui.ActionMenuAdapter.Companion.OPTION_REMOVE
import com.agileburo.anytype.library_page_icon_picker_widget.ui.ActionMenuDivider
import com.agileburo.anytype.presentation.page.picker.DocumentIconPickerViewModel
import com.agileburo.anytype.presentation.page.picker.PageIconPickerViewModelFactory
import com.agileburo.anytype.ui.page.modals.DocumentEmojiIconPickerFragment
import kotlinx.android.synthetic.main.action_toolbar_page_icon.*
import javax.inject.Inject
class DocumentIconActionMenu : BaseFragment(R.layout.action_toolbar_page_icon),
Observer<DocumentIconPickerViewModel.ViewState> {
private val target: String
get() = requireArguments()
.getString(ARG_TARGET_ID_KEY)
?: throw IllegalStateException(MISSING_TARGET_ERROR)
@Inject
lateinit var factory: PageIconPickerViewModelFactory
private val vm by lazy {
ViewModelProviders
.of(this, factory)
.get(DocumentIconPickerViewModel::class.java)
}
override fun onActivityCreated(savedInstanceState: Bundle?) {
super.onActivityCreated(savedInstanceState)
vm.state.observe(viewLifecycleOwner, this)
}
override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
super.onViewCreated(view, savedInstanceState)
container.setOnClickListener { exit() }
arguments?.getString(EMOJI_KEY)?.let { emoji -> logo.text = emoji }
setupLogoTranslation()
setupAdapter()
showMenuWithAnimation()
}
private fun setupLogoTranslation() {
val y = arguments?.getFloat(Y_KEY)
if (y != null && y != 0.0f) {
val delta = y - logo.y
logo.y = y
menu.y = menu.y + delta
}
}
private fun showMenuWithAnimation() {
val xAnim = menu.animate().scaleX(1f).apply {
duration = ANIM_DURATION
startDelay = ANIM_START_DELAY
interpolator = OvershootInterpolator()
}
val yAnim = menu.animate().scaleY(1f).apply {
duration = ANIM_DURATION
startDelay = ANIM_START_DELAY
interpolator = OvershootInterpolator()
}
xAnim.start()
yAnim.start()
}
private fun setupAdapter() {
val drawable = requireContext().getDrawable(R.drawable.action_menu_divider)
checkNotNull(drawable)
val divider = ActionMenuDivider(drawable)
recycler.apply {
addItemDecoration(divider)
adapter = ActionMenuAdapter(
options = intArrayOf(
OPTION_CHOOSE_EMOJI,
OPTION_CHOOSE_RANDOM_EMOJI,
OPTION_CHOOSE_UPLOAD_PHOTO,
OPTION_REMOVE
)
) { option ->
when (option) {
OPTION_CHOOSE_EMOJI -> {
parentFragment?.childFragmentManager?.let { manager ->
manager.popBackStack()
DocumentEmojiIconPickerFragment.newInstance(
context = target,
target = target
).show(manager, null)
}
}
OPTION_REMOVE -> vm.onEvent(
DocumentIconPickerViewModel.Contract.Event.OnRemoveEmojiSelected(
context = target,
target = target
)
)
OPTION_CHOOSE_RANDOM_EMOJI -> vm.onEvent(
DocumentIconPickerViewModel.Contract.Event.OnSetRandomEmojiClicked(
context = target,
target = target
)
)
else -> toast("Not implemented")
}
}
}
}
override fun onChanged(state: DocumentIconPickerViewModel.ViewState) {
when (state) {
is DocumentIconPickerViewModel.ViewState.Exit -> exit()
is DocumentIconPickerViewModel.ViewState.Error -> toast(state.message)
}
}
private fun exit() {
parentFragment?.childFragmentManager?.popBackStack()
}
override fun injectDependencies() {
componentManager().pageIconPickerSubComponent.get().inject(this)
}
override fun releaseDependencies() {
componentManager().pageIconPickerSubComponent.release()
}
companion object {
fun new(
y: Float?,
emoji: String?,
target: String
): DocumentIconActionMenu = DocumentIconActionMenu().apply {
arguments = bundleOf(
Y_KEY to y,
EMOJI_KEY to emoji,
ARG_TARGET_ID_KEY to target
)
}
private const val Y_KEY = "y"
private const val EMOJI_KEY = "emoji"
private const val ANIM_START_DELAY = 200L
private const val ANIM_DURATION = 200L
private const val ARG_TARGET_ID_KEY = "arg.picker.target.id"
private const val MISSING_TARGET_ERROR = "Missing target id"
}
}

View file

@ -0,0 +1,46 @@
<?xml version="1.0" encoding="utf-8"?>
<androidx.constraintlayout.motion.widget.MotionLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
xmlns:tools="http://schemas.android.com/tools"
android:id="@+id/container"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:background="#52000000">
<TextView
android:id="@+id/logo"
android:layout_width="64dp"
android:layout_height="64dp"
android:layout_marginStart="20dp"
android:background="@drawable/rectangle_default_page_logo_background"
android:gravity="center"
android:textColor="@color/emoji_color"
android:textSize="28sp"
android:transitionName="@string/logo_transition"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="parent"
tools:text="🚀" />
<androidx.cardview.widget.CardView
android:scaleX="0.5"
android:scaleY="0.5"
android:id="@+id/menu"
android:layout_width="0dp"
android:layout_height="200dp"
android:layout_marginStart="20dp"
android:layout_marginTop="16dp"
app:cardCornerRadius="10dp"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toBottomOf="@+id/logo"
app:layout_constraintWidth_percent="0.7">
<androidx.recyclerview.widget.RecyclerView
android:id="@+id/recycler"
android:layout_width="match_parent"
android:layout_height="wrap_content"
app:layoutManager="androidx.recyclerview.widget.LinearLayoutManager"
tools:listitem="@layout/action_toolbar_page_icon_item" />
</androidx.cardview.widget.CardView>
</androidx.constraintlayout.motion.widget.MotionLayout>

View file

@ -21,26 +21,6 @@
android:layout_marginTop="6dp"
android:background="@drawable/page_icon_picker_dragger_background" />
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_gravity="center_horizontal"
android:layout_marginTop="30dp"
android:fontFamily="@font/graphik_semibold"
android:text="@string/page_icon"
android:textColor="@color/black"
android:textSize="17sp" />
<TextView
android:id="@+id/remove"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_gravity="end"
android:layout_marginTop="30dp"
android:text="@string/page_icon_picker_remove_text"
android:textColor="#ACA996"
android:textSize="17sp" />
</FrameLayout>
<androidx.recyclerview.widget.RecyclerView

View file

@ -4,8 +4,7 @@ import android.content.Context
import androidx.recyclerview.widget.DividerItemDecoration
import com.agileburo.anytype.core_ui.R
class ListDividerItemDecoration(context: Context) :
DividerItemDecoration(context, VERTICAL) {
class ListDividerItemDecoration(context: Context) : DividerItemDecoration(context, VERTICAL) {
init {
context.getDrawable(R.drawable.divider)?.let {

View file

@ -8,6 +8,7 @@
android:paddingEnd="20dp">
<TextView
android:transitionName="@string/logo_transition"
android:id="@+id/logo"
android:layout_width="64dp"
android:layout_height="64dp"

View file

@ -80,6 +80,7 @@
<dimen name="dp_16">16dp</dimen>
<dimen name="dp_12">12dp</dimen>
<dimen name="dp_48">48dp</dimen>
<dimen name="dp_45">45dp</dimen>
<dimen name="dp_203">203dp</dimen>
<dimen name="roundedTextBorderRadius">4dp</dimen>

View file

@ -202,4 +202,7 @@
<string name="redo">Redo</string>
<string name="copy">Copy</string>
<string name="choose_emoji">Choose emoji</string>
<string name="logo_transition">logo_transition</string>
</resources>

View file

@ -0,0 +1,34 @@
package com.agileburo.anytype.library_page_icon_picker_widget.model
import com.agileburo.anytype.core_ui.common.ViewType
import com.agileburo.anytype.library_page_icon_picker_widget.ui.DocumentEmojiIconPickerViewHolder.Companion.HOLDER_EMOJI_CATEGORY_HEADER
import com.agileburo.anytype.library_page_icon_picker_widget.ui.DocumentEmojiIconPickerViewHolder.Companion.HOLDER_EMOJI_FILTER
import com.agileburo.anytype.library_page_icon_picker_widget.ui.DocumentEmojiIconPickerViewHolder.Companion.HOLDER_EMOJI_ITEM
sealed class DocumentEmojiIconPickerView : ViewType {
/**
* @property alias short name or convenient name for an emoji.
*/
data class Emoji(
val alias: String,
val unicode: String
) : DocumentEmojiIconPickerView() {
override fun getViewType() = HOLDER_EMOJI_ITEM
}
/**
* @property category emoji category
*/
data class GroupHeader(
val category: String
) : DocumentEmojiIconPickerView() {
override fun getViewType() = HOLDER_EMOJI_CATEGORY_HEADER
}
/**
* Emoji filter.
*/
object EmojiFilter : DocumentEmojiIconPickerView() {
override fun getViewType() = HOLDER_EMOJI_FILTER
}
}

View file

@ -1,53 +0,0 @@
package com.agileburo.anytype.library_page_icon_picker_widget.model
import com.agileburo.anytype.core_ui.common.ViewType
import com.agileburo.anytype.library_page_icon_picker_widget.ui.PageIconPickerViewHolder.Companion.HOLDER_CHOOSE_EMOJI
import com.agileburo.anytype.library_page_icon_picker_widget.ui.PageIconPickerViewHolder.Companion.HOLDER_EMOJI_CATEGORY_HEADER
import com.agileburo.anytype.library_page_icon_picker_widget.ui.PageIconPickerViewHolder.Companion.HOLDER_EMOJI_FILTER
import com.agileburo.anytype.library_page_icon_picker_widget.ui.PageIconPickerViewHolder.Companion.HOLDER_EMOJI_ITEM
import com.agileburo.anytype.library_page_icon_picker_widget.ui.PageIconPickerViewHolder.Companion.HOLDER_PICK_RANDOM_EMOJI
import com.agileburo.anytype.library_page_icon_picker_widget.ui.PageIconPickerViewHolder.Companion.HOLDER_UPLOAD_PHOTO
sealed class PageIconPickerView : ViewType {
/**
* @property alias short name or convenient name for an emoji.
*/
data class Emoji(
val alias: String,
val unicode: String
) : PageIconPickerView() {
override fun getViewType() = HOLDER_EMOJI_ITEM
}
/**
* @property category emoji category
*/
data class GroupHeader(
val category: String
) : PageIconPickerView() {
override fun getViewType() = HOLDER_EMOJI_CATEGORY_HEADER
}
/**
* Emoji filter.
*/
object EmojiFilter : PageIconPickerView() {
override fun getViewType() = HOLDER_EMOJI_FILTER
}
/**
* User actions related to emoji picker feature.
*/
sealed class Action : PageIconPickerView() {
object UploadPhoto : Action() {
override fun getViewType() = HOLDER_UPLOAD_PHOTO
}
object PickRandomly : Action() {
override fun getViewType() = HOLDER_PICK_RANDOM_EMOJI
}
object ChooseEmoji : Action() {
override fun getViewType() = HOLDER_CHOOSE_EMOJI
}
}
}

View file

@ -3,8 +3,8 @@ package com.agileburo.anytype.library_page_icon_picker_widget.model
import androidx.recyclerview.widget.DiffUtil
class PageIconPickerViewDiffUtil(
private val old: List<PageIconPickerView>,
private val new: List<PageIconPickerView>
private val old: List<DocumentEmojiIconPickerView>,
private val new: List<DocumentEmojiIconPickerView>
) : DiffUtil.Callback() {
override fun areItemsTheSame(oldItemPosition: Int, newItemPosition: Int): Boolean {

View file

@ -0,0 +1,68 @@
package com.agileburo.anytype.library_page_icon_picker_widget.ui
import android.view.LayoutInflater
import android.view.View
import android.view.ViewGroup
import androidx.recyclerview.widget.RecyclerView
import com.agileburo.anytype.library_page_icon_picker_widget.R
import kotlinx.android.synthetic.main.action_toolbar_page_icon_item.view.*
class ActionMenuAdapter(
private val options : IntArray,
private val onClick: (Int) -> Unit
) : RecyclerView.Adapter<ActionMenuAdapter.ViewHolder>() {
override fun onCreateViewHolder(
parent: ViewGroup, viewType: Int
): ViewHolder = ViewHolder(
view = LayoutInflater.from(parent.context).inflate(
R.layout.action_toolbar_page_icon_item,
parent,
false
)
)
override fun getItemCount(): Int = options.size
override fun onBindViewHolder(
holder: ViewHolder, position: Int
) = holder.bind(options[position], onClick)
class ViewHolder(view: View) : RecyclerView.ViewHolder(view) {
private val title = itemView.title
private val icon = itemView.icon
fun bind(
option: Int,
onClick: (Int) -> Unit
) {
itemView.setOnClickListener { onClick(option) }
when(option) {
OPTION_CHOOSE_EMOJI -> {
title.setText(R.string.page_icon_picker_choose_emoji)
icon.setImageResource(R.drawable.ic_page_icon_picker_choose_emoji)
}
OPTION_CHOOSE_RANDOM_EMOJI -> {
title.setText(R.string.page_icon_picker_pick_emoji_randomly)
icon.setImageResource(R.drawable.ic_page_icon_picker_random_emoji)
}
OPTION_CHOOSE_UPLOAD_PHOTO -> {
title.setText(R.string.page_icon_picker_upload_photo)
icon.setImageResource(R.drawable.ic_page_icon_picker_upload_photo)
}
OPTION_REMOVE -> {
title.setText(R.string.page_icon_picker_remove_text)
icon.setImageResource(R.drawable.ic_remove_page_icon)
}
}
}
}
companion object {
const val OPTION_CHOOSE_EMOJI = 0
const val OPTION_CHOOSE_RANDOM_EMOJI = 1
const val OPTION_CHOOSE_UPLOAD_PHOTO = 2
const val OPTION_REMOVE = 3
}
}

View file

@ -0,0 +1,21 @@
package com.agileburo.anytype.library_page_icon_picker_widget.ui
import android.graphics.Canvas
import android.graphics.drawable.Drawable
import androidx.recyclerview.widget.RecyclerView
class ActionMenuDivider(private val divider: Drawable) : RecyclerView.ItemDecoration() {
override fun onDraw(c: Canvas, parent: RecyclerView, state: RecyclerView.State) {
val dividerLeft = parent.paddingLeft
val dividerRight = parent.width - parent.paddingRight
val count = parent.childCount
for (i in 0..count - 2) {
val child = parent.getChildAt(i)
val params = child.layoutParams as RecyclerView.LayoutParams
val dividerTop = child.bottom + params.bottomMargin
val dividerBottom = dividerTop + divider.intrinsicHeight
divider.setBounds(dividerLeft, dividerTop, dividerRight, dividerBottom)
divider.draw(c)
}
}
}

View file

@ -0,0 +1,85 @@
package com.agileburo.anytype.library_page_icon_picker_widget.ui
import android.view.LayoutInflater
import android.view.ViewGroup
import androidx.core.widget.doOnTextChanged
import androidx.recyclerview.widget.DiffUtil
import androidx.recyclerview.widget.RecyclerView
import com.agileburo.anytype.library_page_icon_picker_widget.R
import com.agileburo.anytype.library_page_icon_picker_widget.model.DocumentEmojiIconPickerView
import com.agileburo.anytype.library_page_icon_picker_widget.model.PageIconPickerViewDiffUtil
import com.agileburo.anytype.library_page_icon_picker_widget.ui.DocumentEmojiIconPickerViewHolder.Companion.HOLDER_EMOJI_CATEGORY_HEADER
import com.agileburo.anytype.library_page_icon_picker_widget.ui.DocumentEmojiIconPickerViewHolder.Companion.HOLDER_EMOJI_FILTER
import com.agileburo.anytype.library_page_icon_picker_widget.ui.DocumentEmojiIconPickerViewHolder.Companion.HOLDER_EMOJI_ITEM
import kotlinx.android.synthetic.main.item_page_icon_picker_emoji_filter.view.*
class DocumentEmojiIconPickerAdapter(
private var views: List<DocumentEmojiIconPickerView>,
private val onFilterQueryChanged: (String) -> Unit,
private val onEmojiClicked: (String, String) -> Unit
) : RecyclerView.Adapter<DocumentEmojiIconPickerViewHolder>() {
override fun onCreateViewHolder(
parent: ViewGroup,
viewType: Int
): DocumentEmojiIconPickerViewHolder {
val inflater = LayoutInflater.from(parent.context)
return when (viewType) {
HOLDER_EMOJI_CATEGORY_HEADER -> DocumentEmojiIconPickerViewHolder.CategoryHeader(
view = inflater.inflate(
R.layout.item_page_icon_picker_emoji_category_header,
parent,
false
)
)
HOLDER_EMOJI_ITEM -> DocumentEmojiIconPickerViewHolder.EmojiItem(
view = LayoutInflater.from(parent.context).inflate(
R.layout.item_page_icon_picker_emoji_item,
parent,
false
)
)
HOLDER_EMOJI_FILTER -> DocumentEmojiIconPickerViewHolder.EmojiFilter(
view = LayoutInflater.from(parent.context).inflate(
R.layout.item_page_icon_picker_emoji_filter,
parent,
false
)
).apply {
itemView.filterInputField.doOnTextChanged { text, _, _, _ ->
onFilterQueryChanged(text.toString())
}
}
else -> throw IllegalStateException("Unexpected view type: $viewType")
}
}
override fun getItemCount(): Int = views.size
override fun getItemViewType(position: Int) = views[position].getViewType()
override fun onBindViewHolder(holder: DocumentEmojiIconPickerViewHolder, position: Int) {
when (holder) {
is DocumentEmojiIconPickerViewHolder.CategoryHeader -> {
holder.bind(views[position] as DocumentEmojiIconPickerView.GroupHeader)
}
is DocumentEmojiIconPickerViewHolder.EmojiItem -> {
holder.bind(
item = views[position] as DocumentEmojiIconPickerView.Emoji,
onEmojiClicked = onEmojiClicked
)
}
}
}
fun update(update: List<DocumentEmojiIconPickerView>) {
val result = DiffUtil.calculateDiff(
PageIconPickerViewDiffUtil(
old = views,
new = update
)
)
views = update
result.dispatchUpdatesTo(this)
}
}

View file

@ -0,0 +1,41 @@
package com.agileburo.anytype.library_page_icon_picker_widget.ui
import android.view.View
import androidx.recyclerview.widget.RecyclerView
import com.agileburo.anytype.library_page_icon_picker_widget.model.DocumentEmojiIconPickerView
import kotlinx.android.synthetic.main.item_page_icon_picker_emoji_category_header.view.*
import kotlinx.android.synthetic.main.item_page_icon_picker_emoji_item.view.*
sealed class DocumentEmojiIconPickerViewHolder(view: View) : RecyclerView.ViewHolder(view) {
class CategoryHeader(view: View) : DocumentEmojiIconPickerViewHolder(view) {
private val category = itemView.category
fun bind(item: DocumentEmojiIconPickerView.GroupHeader) {
category.text = item.category
}
}
class EmojiItem(view: View) : DocumentEmojiIconPickerViewHolder(view) {
private val emoji = itemView.emoji
fun bind(
item: DocumentEmojiIconPickerView.Emoji,
onEmojiClicked: (String, String) -> Unit
) {
emoji.text = item.unicode
itemView.setOnClickListener { onEmojiClicked(item.unicode, item.alias) }
}
}
class EmojiFilter(view: View) : DocumentEmojiIconPickerViewHolder(view)
companion object {
const val HOLDER_EMOJI_CATEGORY_HEADER = 1
const val HOLDER_EMOJI_ITEM = 2
const val HOLDER_EMOJI_FILTER = 3
}
}

View file

@ -1,112 +0,0 @@
package com.agileburo.anytype.library_page_icon_picker_widget.ui
import android.view.LayoutInflater
import android.view.ViewGroup
import androidx.core.widget.doOnTextChanged
import androidx.recyclerview.widget.DiffUtil
import androidx.recyclerview.widget.RecyclerView
import com.agileburo.anytype.library_page_icon_picker_widget.R
import com.agileburo.anytype.library_page_icon_picker_widget.model.PageIconPickerView
import com.agileburo.anytype.library_page_icon_picker_widget.model.PageIconPickerViewDiffUtil
import com.agileburo.anytype.library_page_icon_picker_widget.ui.PageIconPickerViewHolder.Companion.HOLDER_CHOOSE_EMOJI
import com.agileburo.anytype.library_page_icon_picker_widget.ui.PageIconPickerViewHolder.Companion.HOLDER_EMOJI_CATEGORY_HEADER
import com.agileburo.anytype.library_page_icon_picker_widget.ui.PageIconPickerViewHolder.Companion.HOLDER_EMOJI_FILTER
import com.agileburo.anytype.library_page_icon_picker_widget.ui.PageIconPickerViewHolder.Companion.HOLDER_EMOJI_ITEM
import com.agileburo.anytype.library_page_icon_picker_widget.ui.PageIconPickerViewHolder.Companion.HOLDER_PICK_RANDOM_EMOJI
import com.agileburo.anytype.library_page_icon_picker_widget.ui.PageIconPickerViewHolder.Companion.HOLDER_UPLOAD_PHOTO
import kotlinx.android.synthetic.main.item_page_icon_picker_emoji_filter.view.*
class PageIconPickerAdapter(
private var views: List<PageIconPickerView>,
private val onUploadPhotoClicked: () -> Unit,
private val onSetRandomEmojiClicked: () -> Unit,
private val onFilterQueryChanged: (String) -> Unit,
private val onEmojiClicked: (String, String) -> Unit
) : RecyclerView.Adapter<PageIconPickerViewHolder>() {
override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): PageIconPickerViewHolder {
val inflater = LayoutInflater.from(parent.context)
return when (viewType) {
HOLDER_UPLOAD_PHOTO -> PageIconPickerViewHolder.UploadPhoto(
view = inflater.inflate(
R.layout.item_page_icon_picker_upload_photo,
parent,
false
)
).apply {
itemView.setOnClickListener { onUploadPhotoClicked() }
}
HOLDER_PICK_RANDOM_EMOJI -> PageIconPickerViewHolder.PickRandom(
view = inflater.inflate(
R.layout.item_page_icon_picker_pick_emoji_randomly,
parent,
false
)
).apply {
itemView.setOnClickListener { onSetRandomEmojiClicked() }
}
HOLDER_CHOOSE_EMOJI -> PageIconPickerViewHolder.ChooseEmoji(
view = inflater.inflate(
R.layout.item_page_icon_picker_choose_emoji,
parent,
false
)
)
HOLDER_EMOJI_CATEGORY_HEADER -> PageIconPickerViewHolder.CategoryHeader(
view = inflater.inflate(
R.layout.item_page_icon_picker_emoji_category_header,
parent,
false
)
)
HOLDER_EMOJI_ITEM -> PageIconPickerViewHolder.EmojiItem(
view = LayoutInflater.from(parent.context).inflate(
R.layout.item_page_icon_picker_emoji_item,
parent,
false
)
)
HOLDER_EMOJI_FILTER -> PageIconPickerViewHolder.EmojiFilter(
view = LayoutInflater.from(parent.context).inflate(
R.layout.item_page_icon_picker_emoji_filter,
parent,
false
)
).apply {
itemView.filterInputField.doOnTextChanged { text, _, _, _ ->
onFilterQueryChanged(text.toString())
}
}
else -> throw IllegalStateException("Unexpected view type: $viewType")
}
}
override fun getItemCount(): Int = views.size
override fun getItemViewType(position: Int) = views[position].getViewType()
override fun onBindViewHolder(holder: PageIconPickerViewHolder, position: Int) {
when (holder) {
is PageIconPickerViewHolder.CategoryHeader -> {
holder.bind(views[position] as PageIconPickerView.GroupHeader)
}
is PageIconPickerViewHolder.EmojiItem -> {
holder.bind(
item = views[position] as PageIconPickerView.Emoji,
onEmojiClicked = onEmojiClicked
)
}
}
}
fun update(update: List<PageIconPickerView>) {
val result = DiffUtil.calculateDiff(
PageIconPickerViewDiffUtil(
old = views,
new = update
)
)
views = update
result.dispatchUpdatesTo(this)
}
}

View file

@ -1,50 +0,0 @@
package com.agileburo.anytype.library_page_icon_picker_widget.ui
import android.view.View
import androidx.recyclerview.widget.RecyclerView
import com.agileburo.anytype.library_page_icon_picker_widget.model.PageIconPickerView
import kotlinx.android.synthetic.main.item_page_icon_picker_emoji_category_header.view.*
import kotlinx.android.synthetic.main.item_page_icon_picker_emoji_item.view.*
sealed class PageIconPickerViewHolder(view: View) : RecyclerView.ViewHolder(view) {
class UploadPhoto(view: View) : PageIconPickerViewHolder(view)
class PickRandom(view: View) : PageIconPickerViewHolder(view)
class ChooseEmoji(view: View) : PageIconPickerViewHolder(view)
class CategoryHeader(view: View) : PageIconPickerViewHolder(view) {
private val category = itemView.category
fun bind(item: PageIconPickerView.GroupHeader) {
category.text = item.category
}
}
class EmojiItem(view: View) : PageIconPickerViewHolder(view) {
private val emoji = itemView.emoji
fun bind(
item: PageIconPickerView.Emoji,
onEmojiClicked: (String, String) -> Unit
) {
emoji.text = item.unicode
itemView.setOnClickListener { onEmojiClicked(item.unicode, item.alias) }
}
}
class EmojiFilter(view: View) : PageIconPickerViewHolder(view)
companion object {
const val HOLDER_UPLOAD_PHOTO = 0
const val HOLDER_PICK_RANDOM_EMOJI = 1
const val HOLDER_CHOOSE_EMOJI = 2
const val HOLDER_EMOJI_CATEGORY_HEADER = 3
const val HOLDER_EMOJI_ITEM = 4
const val HOLDER_EMOJI_FILTER = 5
}
}

View file

@ -0,0 +1,7 @@
<shape xmlns:android="http://schemas.android.com/apk/res/android"
android:shape="rectangle">
<size
android:width="1dp"
android:height="1dp" />
<solid android:color="#EAE9E0" />
</shape>

View file

@ -4,17 +4,17 @@
android:viewportWidth="24"
android:viewportHeight="24">
<path
android:fillColor="#2C2B27"
android:fillColor="#ACA996"
android:fillType="evenOdd"
android:pathData="M11.999,21C16.9696,21 20.999,16.9706 20.999,12C20.999,7.0294 16.9696,3 11.999,3C7.0285,3 2.999,7.0294 2.999,12C2.999,16.9706 7.0285,21 11.999,21ZM11.999,23C18.0742,23 22.999,18.0751 22.999,12C22.999,5.9249 18.0742,1 11.999,1C5.9239,1 0.999,5.9249 0.999,12C0.999,18.0751 5.9239,23 11.999,23Z" />
<path
android:fillColor="#2C2B27"
android:fillColor="#ACA996"
android:pathData="M16.999,9.5C16.999,10.3284 16.3275,11 15.499,11C14.6706,11 13.999,10.3284 13.999,9.5C13.999,8.6716 14.6706,8 15.499,8C16.3275,8 16.999,8.6716 16.999,9.5Z" />
<path
android:fillColor="#2C2B27"
android:fillColor="#ACA996"
android:pathData="M9.999,9.5C9.999,10.3284 9.3274,11 8.499,11C7.6706,11 6.999,10.3284 6.999,9.5C6.999,8.6716 7.6706,8 8.499,8C9.3274,8 9.999,8.6716 9.999,9.5Z" />
<path
android:fillColor="#2C2B27"
android:fillColor="#ACA996"
android:fillType="evenOdd"
android:pathData="M5.2889,14C6.1495,16.8915 8.828,19 11.9991,19C15.1701,19 17.8486,16.8915 18.7092,14H5.2889Z" />
</vector>

View file

@ -7,20 +7,20 @@
android:fillColor="#00000000"
android:pathData="M4.998,3L18.9981,3A2,2 0,0 1,20.9981 5L20.9981,19A2,2 0,0 1,18.9981 21L4.998,21A2,2 0,0 1,2.998 19L2.998,5A2,2 0,0 1,4.998 3z"
android:strokeWidth="2"
android:strokeColor="#2C2B27" />
android:strokeColor="#ACA996" />
<path
android:fillColor="#2C2B27"
android:fillColor="#ACA996"
android:pathData="M7.9981,8m-1.5,0a1.5,1.5 0,1 1,3 0a1.5,1.5 0,1 1,-3 0" />
<path
android:fillColor="#2C2B27"
android:fillColor="#ACA996"
android:pathData="M15.998,8m-1.5,0a1.5,1.5 0,1 1,3 0a1.5,1.5 0,1 1,-3 0" />
<path
android:fillColor="#2C2B27"
android:fillColor="#ACA996"
android:pathData="M7.9981,16m-1.5,0a1.5,1.5 0,1 1,3 0a1.5,1.5 0,1 1,-3 0" />
<path
android:fillColor="#2C2B27"
android:fillColor="#ACA996"
android:pathData="M15.998,16m-1.5,0a1.5,1.5 0,1 1,3 0a1.5,1.5 0,1 1,-3 0" />
<path
android:fillColor="#2C2B27"
android:fillColor="#ACA996"
android:pathData="M11.998,12m-1.5,0a1.5,1.5 0,1 1,3 0a1.5,1.5 0,1 1,-3 0" />
</vector>

View file

@ -4,13 +4,13 @@
android:viewportWidth="24"
android:viewportHeight="24">
<path
android:fillColor="#2C2B27"
android:fillColor="#ACA996"
android:pathData="M10.999,3C10.999,2.4477 11.4467,2 11.999,2C12.5513,2 12.999,2.4477 12.999,3V17C12.999,17.5523 12.5513,18 11.999,18C11.4467,18 10.999,17.5523 10.999,17V3Z" />
<path
android:fillColor="#2C2B27"
android:fillColor="#ACA996"
android:pathData="M4.999,22C4.4467,22 3.999,21.5523 3.999,21C3.999,20.4477 4.4467,20 4.999,20H18.999C19.5513,20 19.999,20.4477 19.999,21C19.999,21.5523 19.5513,22 18.999,22H4.999Z" />
<path
android:fillColor="#2C2B27"
android:fillColor="#ACA996"
android:fillType="evenOdd"
android:pathData="M11.999,1.5858L19.7061,9.2929C20.0967,9.6834 20.0967,10.3166 19.7061,10.7071C19.3156,11.0977 18.6824,11.0977 18.2919,10.7071L11.999,4.4142L5.7061,10.7071C5.3156,11.0977 4.6824,11.0977 4.2919,10.7071C3.9014,10.3166 3.9014,9.6834 4.2919,9.2929L11.999,1.5858Z" />
</vector>

View file

@ -0,0 +1,23 @@
<vector xmlns:android="http://schemas.android.com/apk/res/android"
android:width="24dp"
android:height="24dp"
android:viewportWidth="24"
android:viewportHeight="24">
<path
android:pathData="M9.5,8H11V18H9.5V8Z"
android:fillColor="#ACA996"/>
<path
android:pathData="M13,8H14.5V18H13V8Z"
android:fillColor="#ACA996"/>
<path
android:pathData="M4.7431,6.5C4.3288,6.5 4,6.1642 4,5.75C4,5.3358 4.3358,5 4.75,5L19.25,5C19.6642,5 20,5.3358 20,5.75C20,6.1642 19.6705,6.5 19.2563,6.5C16.4869,6.5 7.4099,6.5 4.7431,6.5Z"
android:fillColor="#ACA996"/>
<path
android:pathData="M14,3.5H10V5H14V3.5ZM10,2C9.1716,2 8.5,2.6716 8.5,3.5V6.5H15.5V3.5C15.5,2.6716 14.8284,2 14,2H10Z"
android:fillColor="#ACA996"
android:fillType="evenOdd"/>
<path
android:pathData="M5.2656,5L5.8686,18.1376C5.9421,19.7392 7.2621,21 8.8655,21H15.1372C16.7395,21 18.059,19.7409 18.1339,18.1403L18.75,4.9844L5.2656,5ZM6.836,6.4982L7.367,18.0688C7.4038,18.8696 8.0638,19.5 8.8655,19.5H15.1372C15.9383,19.5 16.5981,18.8704 16.6356,18.0702L17.178,6.4862L6.836,6.4982Z"
android:fillColor="#ACA996"
android:fillType="evenOdd"/>
</vector>

View file

@ -0,0 +1,28 @@
<?xml version="1.0" encoding="utf-8"?>
<FrameLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
android:background="?attr/selectableItemBackgroundBorderless"
android:layout_width="match_parent" android:layout_height="wrap_content">
<TextView
android:layout_gravity="center_vertical"
android:layout_marginStart="16dp"
android:textColor="@color/black"
tools:text="Choose emoji"
android:fontFamily="@font/inter_regular"
android:textSize="17sp"
android:id="@+id/title"
android:layout_width="wrap_content"
android:layout_height="wrap_content"/>
<ImageView
tools:background="@drawable/circle_solid_default"
android:layout_marginEnd="16dp"
android:layout_marginTop="12dp"
android:layout_marginBottom="12dp"
android:layout_gravity="end"
android:id="@+id/icon"
android:layout_width="24dp"
android:layout_height="24dp"/>
</FrameLayout>

View file

@ -0,0 +1,90 @@
package com.agileburo.anytype.library_page_icon_picker_widget
import com.agileburo.anytype.library_page_icon_picker_widget.model.DocumentEmojiIconPickerView
import com.agileburo.anytype.library_page_icon_picker_widget.model.PageIconPickerViewDiffUtil
import org.junit.Test
import kotlin.test.assertEquals
class DocumentEmojiIconPickerViewDiffUtilTest {
@Test
fun `two emoji-filter items should be considered the same`() {
val old = listOf(
DocumentEmojiIconPickerView.EmojiFilter
)
val new = listOf(
DocumentEmojiIconPickerView.EmojiFilter
)
val util = PageIconPickerViewDiffUtil(
old = old,
new = new
)
val result = util.areItemsTheSame(0, 0)
assertEquals(
expected = true,
actual = result
)
}
@Test
fun `two emoji items should be considered the same`() {
val old = listOf(
DocumentEmojiIconPickerView.Emoji(
alias = "grining",
unicode = "U+13131"
)
)
val new = listOf(
DocumentEmojiIconPickerView.Emoji(
alias = "grining",
unicode = "U+13131"
)
)
val util = PageIconPickerViewDiffUtil(
old = old,
new = new
)
val result = util.areItemsTheSame(0, 0)
assertEquals(
expected = true,
actual = result
)
}
@Test
fun `two emoji items should be considered different`() {
val old = listOf(
DocumentEmojiIconPickerView.Emoji(
alias = "smile",
unicode = "U+13131"
)
)
val new = listOf(
DocumentEmojiIconPickerView.Emoji(
alias = "grining",
unicode = "U+13131"
)
)
val util = PageIconPickerViewDiffUtil(
old = old,
new = new
)
val result = util.areItemsTheSame(0, 0)
assertEquals(
expected = false,
actual = result
)
}
}

View file

@ -1,159 +0,0 @@
package com.agileburo.anytype.library_page_icon_picker_widget
import com.agileburo.anytype.library_page_icon_picker_widget.model.PageIconPickerView
import com.agileburo.anytype.library_page_icon_picker_widget.model.PageIconPickerViewDiffUtil
import org.junit.Test
import kotlin.test.assertEquals
class PageIconPickerViewDiffUtilTest {
@Test
fun `two emoji-filter items should be considered the same`() {
val old = listOf(
PageIconPickerView.EmojiFilter
)
val new = listOf(
PageIconPickerView.EmojiFilter
)
val util = PageIconPickerViewDiffUtil(
old = old,
new = new
)
val result = util.areItemsTheSame(0, 0)
assertEquals(
expected = true,
actual = result
)
}
@Test
fun `two upload-photo-action items should be considered the same`() {
val old = listOf(
PageIconPickerView.Action.UploadPhoto
)
val new = listOf(
PageIconPickerView.Action.UploadPhoto
)
val util = PageIconPickerViewDiffUtil(
old = old,
new = new
)
val result = util.areItemsTheSame(0, 0)
assertEquals(
expected = true,
actual = result
)
}
@Test
fun `two choose-emoji-action items should be considered the same`() {
val old = listOf(
PageIconPickerView.Action.ChooseEmoji
)
val new = listOf(
PageIconPickerView.Action.ChooseEmoji
)
val util = PageIconPickerViewDiffUtil(
old = old,
new = new
)
val result = util.areItemsTheSame(0, 0)
assertEquals(
expected = true,
actual = result
)
}
@Test
fun `two pick-random-emoji-action items should be considered the same`() {
val old = listOf(
PageIconPickerView.Action.PickRandomly
)
val new = listOf(
PageIconPickerView.Action.PickRandomly
)
val util = PageIconPickerViewDiffUtil(
old = old,
new = new
)
val result = util.areItemsTheSame(0, 0)
assertEquals(
expected = true,
actual = result
)
}
@Test
fun `two emoji items should be considered the same`() {
val old = listOf(
PageIconPickerView.Emoji(
alias = "grining",
unicode = "U+13131"
)
)
val new = listOf(
PageIconPickerView.Emoji(
alias = "grining",
unicode = "U+13131"
)
)
val util = PageIconPickerViewDiffUtil(
old = old,
new = new
)
val result = util.areItemsTheSame(0, 0)
assertEquals(
expected = true,
actual = result
)
}
@Test
fun `two emoji items should be considered different`() {
val old = listOf(
PageIconPickerView.Emoji(
alias = "smile",
unicode = "U+13131"
)
)
val new = listOf(
PageIconPickerView.Emoji(
alias = "grining",
unicode = "U+13131"
)
)
val util = PageIconPickerViewDiffUtil(
old = old,
new = new
)
val result = util.areItemsTheSame(0, 0)
assertEquals(
expected = false,
actual = result
)
}
}

View file

@ -1627,7 +1627,7 @@ class PageViewModel(
}
fun onPageIconClicked() {
dispatch(Command.OpenPagePicker(context))
dispatch(Command.OpenDocumentIconActionMenu(context))
}
private fun onFileClicked(id: String) {

View file

@ -5,7 +5,12 @@ import com.agileburo.anytype.domain.common.Id
import com.agileburo.anytype.domain.common.Url
sealed class Command {
data class OpenPagePicker(
data class OpenDocumentIconActionMenu(
val target: String
) : Command()
data class OpenDocumentEmojiIconPicker(
val target: String
) : Command()

View file

@ -4,11 +4,11 @@ import androidx.lifecycle.viewModelScope
import com.agileburo.anytype.core_utils.ui.ViewStateViewModel
import com.agileburo.anytype.domain.base.Either
import com.agileburo.anytype.domain.icon.SetIconName
import com.agileburo.anytype.library_page_icon_picker_widget.model.PageIconPickerView
import com.agileburo.anytype.library_page_icon_picker_widget.model.DocumentEmojiIconPickerView
import com.agileburo.anytype.presentation.common.StateReducer
import com.agileburo.anytype.presentation.page.picker.PageIconPickerViewModel.Contract.Event
import com.agileburo.anytype.presentation.page.picker.PageIconPickerViewModel.Contract.State
import com.agileburo.anytype.presentation.page.picker.PageIconPickerViewModel.ViewState
import com.agileburo.anytype.presentation.page.picker.DocumentIconPickerViewModel.Contract.Event
import com.agileburo.anytype.presentation.page.picker.DocumentIconPickerViewModel.Contract.State
import com.agileburo.anytype.presentation.page.picker.DocumentIconPickerViewModel.ViewState
import com.vdurmont.emoji.Emoji
import com.vdurmont.emoji.EmojiManager
import kotlinx.coroutines.Dispatchers
@ -17,7 +17,7 @@ import kotlinx.coroutines.channels.ConflatedBroadcastChannel
import kotlinx.coroutines.flow.*
import kotlinx.coroutines.withContext
class PageIconPickerViewModel(
class DocumentIconPickerViewModel(
private val setIconName: SetIconName
) : ViewStateViewModel<ViewState>(), StateReducer<State, Event> {
@ -30,10 +30,7 @@ class PageIconPickerViewModel(
private val headers = listOf(
PageIconPickerView.Action.UploadPhoto,
PageIconPickerView.Action.PickRandomly,
PageIconPickerView.Action.ChooseEmoji,
PageIconPickerView.EmojiFilter
DocumentEmojiIconPickerView.EmojiFilter
)
init {
@ -51,7 +48,6 @@ class PageIconPickerViewModel(
.map { state ->
when {
state.error != null -> ViewState.Error(state.error)
state.isLoading -> ViewState.Loading
state.isCompleted -> ViewState.Exit
else -> ViewState.Success(
views = headers + map(state.selection)
@ -142,12 +138,12 @@ class PageIconPickerViewModel(
}
private suspend fun pickRandomEmoji(emojis: List<Emoji>): Emoji = withContext(Dispatchers.IO) {
emojis.random()
EmojiManager.getAll().random()
}
private suspend fun map(emojis: List<Emoji>) = withContext(Dispatchers.IO) {
emojis.map { emoji ->
PageIconPickerView.Emoji(
DocumentEmojiIconPickerView.Emoji(
alias = emoji.aliases.first(),
/**
* Fix pirate flag emoji render, after fixing
@ -176,7 +172,7 @@ class PageIconPickerViewModel(
sealed class ViewState {
object Loading : ViewState()
object Exit : ViewState()
data class Success(val views: List<PageIconPickerView>) : ViewState()
data class Success(val views: List<DocumentEmojiIconPickerView>) : ViewState()
data class Error(val message: String) : ViewState()
}

View file

@ -9,7 +9,7 @@ class PageIconPickerViewModelFactory(
) : ViewModelProvider.Factory {
@Suppress("UNCHECKED_CAST")
override fun <T : ViewModel?> create(modelClass: Class<T>): T = PageIconPickerViewModel(
override fun <T : ViewModel?> create(modelClass: Class<T>): T = DocumentIconPickerViewModel(
setIconName = setIconName
) as T
}