mirror of
https://github.com/anyproto/anytype-kotlin.git
synced 2025-06-08 05:47:05 +09:00
Editor | Enhancement | Add Callout set icon logic (#2372)
This commit is contained in:
parent
8d23f59955
commit
62f96685be
61 changed files with 696 additions and 694 deletions
|
@ -56,6 +56,7 @@ import com.anytypeio.anytype.di.feature.SetupNewAccountModule
|
|||
import com.anytypeio.anytype.di.feature.SetupSelectedAccountModule
|
||||
import com.anytypeio.anytype.di.feature.SplashModule
|
||||
import com.anytypeio.anytype.di.feature.StartLoginModule
|
||||
import com.anytypeio.anytype.di.feature.TextBlockIconPickerModule
|
||||
import com.anytypeio.anytype.di.feature.ViewerCustomizeModule
|
||||
import com.anytypeio.anytype.di.feature.ViewerFilterModule
|
||||
import com.anytypeio.anytype.di.feature.ViewerRelationsModule
|
||||
|
@ -228,6 +229,14 @@ class ComponentManager(
|
|||
.build()
|
||||
}
|
||||
|
||||
val textBlockIconPickerComponent = DependentComponentMap { ctx ->
|
||||
editorComponent
|
||||
.get(ctx)
|
||||
.textBlockIconPickerComponent()
|
||||
.module(TextBlockIconPickerModule)
|
||||
.build()
|
||||
}
|
||||
|
||||
val objectSetIconPickerComponent = DependentComponentMap { ctx ->
|
||||
objectSetComponent
|
||||
.get(ctx)
|
||||
|
|
|
@ -5,14 +5,19 @@ import com.anytypeio.anytype.core_models.Payload
|
|||
import com.anytypeio.anytype.core_utils.di.scope.PerModal
|
||||
import com.anytypeio.anytype.domain.block.repo.BlockRepository
|
||||
import com.anytypeio.anytype.domain.icon.RemoveDocumentIcon
|
||||
import com.anytypeio.anytype.domain.icon.RemoveTextBlockIcon
|
||||
import com.anytypeio.anytype.domain.icon.SetDocumentEmojiIcon
|
||||
import com.anytypeio.anytype.domain.icon.SetDocumentImageIcon
|
||||
import com.anytypeio.anytype.domain.icon.SetTextBlockEmoji
|
||||
import com.anytypeio.anytype.domain.icon.SetTextBlockImage
|
||||
import com.anytypeio.anytype.emojifier.data.Emoji
|
||||
import com.anytypeio.anytype.emojifier.suggest.EmojiSuggester
|
||||
import com.anytypeio.anytype.presentation.editor.picker.ObjectIconPickerViewModelFactory
|
||||
import com.anytypeio.anytype.presentation.editor.picker.ObjectSetIconPickerViewModelFactory
|
||||
import com.anytypeio.anytype.presentation.editor.picker.TextBlockIconPickerViewModelFactory
|
||||
import com.anytypeio.anytype.presentation.util.Dispatcher
|
||||
import com.anytypeio.anytype.ui.editor.modals.ObjectIconPickerFragment
|
||||
import com.anytypeio.anytype.ui.editor.modals.TextBlockIconPickerFragment
|
||||
import com.anytypeio.anytype.ui.sets.ObjectSetIconPickerFragment
|
||||
import dagger.Module
|
||||
import dagger.Provides
|
||||
|
@ -31,6 +36,19 @@ interface ObjectIconPickerComponent {
|
|||
fun inject(fragment: ObjectIconPickerFragment)
|
||||
}
|
||||
|
||||
@Subcomponent(modules = [TextBlockIconPickerModule::class])
|
||||
@PerModal
|
||||
interface TextBlockIconPickerComponent {
|
||||
|
||||
@Subcomponent.Builder
|
||||
interface Builder {
|
||||
fun module(module: TextBlockIconPickerModule): Builder
|
||||
fun build(): TextBlockIconPickerComponent
|
||||
}
|
||||
|
||||
fun inject(fragment: TextBlockIconPickerFragment)
|
||||
}
|
||||
|
||||
@Subcomponent(modules = [ObjectIconPickerBaseModule::class, ObjectSetIconPickerModule::class])
|
||||
@PerModal
|
||||
interface ObjectSetIconPickerComponent {
|
||||
|
@ -46,6 +64,7 @@ interface ObjectSetIconPickerComponent {
|
|||
|
||||
@Module
|
||||
object ObjectIconPickerBaseModule {
|
||||
|
||||
@Provides
|
||||
@PerModal
|
||||
fun provideSetDocumentEmojiIconUseCase(
|
||||
|
@ -65,6 +84,7 @@ object ObjectIconPickerBaseModule {
|
|||
|
||||
@Module
|
||||
object ObjectIconPickerModule {
|
||||
|
||||
@Provides
|
||||
@PerModal
|
||||
fun provideViewModelFactory(
|
||||
|
@ -85,6 +105,53 @@ object ObjectIconPickerModule {
|
|||
)
|
||||
}
|
||||
|
||||
@Module
|
||||
object TextBlockIconPickerModule {
|
||||
|
||||
@Provides
|
||||
@PerModal
|
||||
fun provideSetEmojiIcon(
|
||||
repo: BlockRepository
|
||||
): SetTextBlockEmoji = SetTextBlockEmoji(
|
||||
repo = repo
|
||||
)
|
||||
|
||||
@Provides
|
||||
@PerModal
|
||||
fun provideRemoveIcon(
|
||||
repo: BlockRepository
|
||||
): RemoveTextBlockIcon = RemoveTextBlockIcon(
|
||||
repo = repo
|
||||
)
|
||||
|
||||
@Provides
|
||||
@PerModal
|
||||
fun provideSetImage(
|
||||
repo: BlockRepository
|
||||
): SetTextBlockImage = SetTextBlockImage(
|
||||
repo = repo
|
||||
)
|
||||
|
||||
@Provides
|
||||
@PerModal
|
||||
fun provideViewModelFactory(
|
||||
setEmojiIcon: SetTextBlockEmoji,
|
||||
setImageIcon: SetTextBlockImage,
|
||||
removeDocumentIcon: RemoveTextBlockIcon,
|
||||
emojiSuggester: EmojiSuggester,
|
||||
dispatcher: Dispatcher<Payload>,
|
||||
analytics: Analytics
|
||||
): TextBlockIconPickerViewModelFactory = TextBlockIconPickerViewModelFactory(
|
||||
setEmojiIcon = setEmojiIcon,
|
||||
setImageIcon = setImageIcon,
|
||||
removeDocumentIcon = removeDocumentIcon,
|
||||
emojiSuggester = emojiSuggester,
|
||||
emojiProvider = Emoji,
|
||||
dispatcher = dispatcher,
|
||||
analytics = analytics
|
||||
)
|
||||
}
|
||||
|
||||
@Module
|
||||
object ObjectSetIconPickerModule {
|
||||
@Provides
|
||||
|
|
|
@ -124,6 +124,7 @@ interface EditorSubComponent {
|
|||
fun inject(fragment: EditorFragment)
|
||||
|
||||
fun objectIconPickerComponent(): ObjectIconPickerComponent.Builder
|
||||
fun textBlockIconPickerComponent(): TextBlockIconPickerComponent.Builder
|
||||
|
||||
// Relations
|
||||
|
||||
|
|
|
@ -17,7 +17,6 @@ import com.anytypeio.anytype.data.auth.repo.InfrastructureDataRepository
|
|||
import com.anytypeio.anytype.data.auth.repo.UserSettingsCache
|
||||
import com.anytypeio.anytype.data.auth.repo.UserSettingsDataRepository
|
||||
import com.anytypeio.anytype.data.auth.repo.block.BlockDataRepository
|
||||
import com.anytypeio.anytype.data.auth.repo.block.BlockDataStoreFactory
|
||||
import com.anytypeio.anytype.data.auth.repo.block.BlockRemote
|
||||
import com.anytypeio.anytype.data.auth.repo.block.BlockRemoteDataStore
|
||||
import com.anytypeio.anytype.data.auth.repo.unsplash.UnsplashDataRepository
|
||||
|
@ -190,20 +189,9 @@ object DataModule {
|
|||
@Provides
|
||||
@Singleton
|
||||
fun provideBlockRepository(
|
||||
factory: BlockDataStoreFactory
|
||||
blockRemoteDataStore: BlockRemoteDataStore
|
||||
): BlockRepository {
|
||||
return BlockDataRepository(
|
||||
factory = factory
|
||||
)
|
||||
}
|
||||
|
||||
@JvmStatic
|
||||
@Provides
|
||||
@Singleton
|
||||
fun provideBlockDataStoreFactory(
|
||||
blockRemoteDataStore: BlockRemoteDataStore
|
||||
): BlockDataStoreFactory {
|
||||
return BlockDataStoreFactory(
|
||||
remote = blockRemoteDataStore
|
||||
)
|
||||
}
|
||||
|
|
|
@ -100,7 +100,6 @@ import com.anytypeio.anytype.presentation.editor.Editor
|
|||
import com.anytypeio.anytype.presentation.editor.EditorViewModel
|
||||
import com.anytypeio.anytype.presentation.editor.EditorViewModelFactory
|
||||
import com.anytypeio.anytype.presentation.editor.Snack
|
||||
import com.anytypeio.anytype.presentation.editor.editor.BlockDimensions
|
||||
import com.anytypeio.anytype.presentation.editor.editor.Command
|
||||
import com.anytypeio.anytype.presentation.editor.editor.Markup
|
||||
import com.anytypeio.anytype.presentation.editor.editor.ThemeColor
|
||||
|
@ -119,10 +118,11 @@ import com.anytypeio.anytype.ui.editor.cover.SelectCoverObjectFragment
|
|||
import com.anytypeio.anytype.ui.editor.gallery.FullScreenPictureFragment
|
||||
import com.anytypeio.anytype.ui.editor.layout.ObjectLayoutFragment
|
||||
import com.anytypeio.anytype.ui.editor.modals.CreateBookmarkFragment
|
||||
import com.anytypeio.anytype.ui.editor.modals.ObjectIconPickerBaseFragment
|
||||
import com.anytypeio.anytype.ui.editor.modals.IconPickerFragmentBase
|
||||
import com.anytypeio.anytype.ui.editor.modals.SelectProgrammingLanguageFragment
|
||||
import com.anytypeio.anytype.ui.editor.modals.SelectProgrammingLanguageReceiver
|
||||
import com.anytypeio.anytype.ui.editor.modals.SetLinkFragment
|
||||
import com.anytypeio.anytype.ui.editor.modals.TextBlockIconPickerFragment
|
||||
import com.anytypeio.anytype.ui.editor.sheets.ObjectMenuBaseFragment
|
||||
import com.anytypeio.anytype.ui.editor.sheets.ObjectMenuBaseFragment.DocumentMenuActionReceiver
|
||||
import com.anytypeio.anytype.ui.linking.LinkToObjectFragment
|
||||
|
@ -862,13 +862,17 @@ open class EditorFragment : NavigationFragment<FragmentEditorBinding>(R.layout.f
|
|||
is Command.OpenDocumentImagePicker -> {
|
||||
pickerDelegate.openFilePicker(command.mimeType, REQUEST_PROFILE_IMAGE_CODE)
|
||||
}
|
||||
is Command.OpenDocumentEmojiIconPicker -> {
|
||||
is Command.OpenTextBlockIconPicker -> {
|
||||
TextBlockIconPickerFragment.new(
|
||||
context = ctx, blockId = command.block
|
||||
).show(childFragmentManager, null)
|
||||
}
|
||||
Command.OpenDocumentEmojiIconPicker -> {
|
||||
hideSoftInput()
|
||||
findNavController().navigate(
|
||||
R.id.action_pageScreen_to_objectIconPickerScreen,
|
||||
bundleOf(
|
||||
ObjectIconPickerBaseFragment.ARG_CONTEXT_ID_KEY to ctx,
|
||||
ObjectIconPickerBaseFragment.ARG_TARGET_ID_KEY to command.target
|
||||
IconPickerFragmentBase.ARG_CONTEXT_ID_KEY to ctx,
|
||||
)
|
||||
)
|
||||
}
|
||||
|
@ -1893,8 +1897,7 @@ open class EditorFragment : NavigationFragment<FragmentEditorBinding>(R.layout.f
|
|||
findNavController().navigate(
|
||||
R.id.objectIconPickerScreen,
|
||||
bundleOf(
|
||||
ObjectIconPickerBaseFragment.ARG_CONTEXT_ID_KEY to ctx,
|
||||
ObjectIconPickerBaseFragment.ARG_TARGET_ID_KEY to ctx,
|
||||
IconPickerFragmentBase.ARG_CONTEXT_ID_KEY to ctx,
|
||||
)
|
||||
)
|
||||
}
|
||||
|
|
|
@ -10,13 +10,13 @@ import android.view.ViewGroup
|
|||
import android.widget.EditText
|
||||
import androidx.activity.result.contract.ActivityResultContracts
|
||||
import androidx.core.content.ContextCompat
|
||||
import androidx.core.os.bundleOf
|
||||
import androidx.core.widget.doAfterTextChanged
|
||||
import androidx.fragment.app.viewModels
|
||||
import androidx.lifecycle.lifecycleScope
|
||||
import androidx.recyclerview.widget.GridLayoutManager
|
||||
import com.anytypeio.anytype.R
|
||||
import com.anytypeio.anytype.core_models.Id
|
||||
import com.anytypeio.anytype.core_utils.ext.GetImageContract
|
||||
import com.anytypeio.anytype.core_utils.ext.arg
|
||||
import com.anytypeio.anytype.core_utils.ext.invisible
|
||||
import com.anytypeio.anytype.core_utils.ext.parseImagePath
|
||||
import com.anytypeio.anytype.core_utils.ext.showSnackbar
|
||||
|
@ -25,31 +25,27 @@ import com.anytypeio.anytype.core_utils.ext.toast
|
|||
import com.anytypeio.anytype.core_utils.ext.visible
|
||||
import com.anytypeio.anytype.core_utils.ui.BaseBottomSheetTextInputFragment
|
||||
import com.anytypeio.anytype.databinding.FragmentPageIconPickerBinding
|
||||
import com.anytypeio.anytype.di.common.componentManager
|
||||
import com.anytypeio.anytype.library_page_icon_picker_widget.ui.DocumentEmojiIconPickerAdapter
|
||||
import com.anytypeio.anytype.presentation.editor.picker.EmojiPickerView.Companion.HOLDER_EMOJI_CATEGORY_HEADER
|
||||
import com.anytypeio.anytype.presentation.editor.picker.EmojiPickerView.Companion.HOLDER_EMOJI_ITEM
|
||||
import com.anytypeio.anytype.presentation.editor.picker.ObjectIconPickerBaseViewModel
|
||||
import com.anytypeio.anytype.presentation.editor.picker.ObjectIconPickerBaseViewModel.ViewState
|
||||
import com.anytypeio.anytype.presentation.editor.picker.ObjectIconPickerViewModel
|
||||
import com.anytypeio.anytype.presentation.editor.picker.ObjectIconPickerViewModelFactory
|
||||
import com.anytypeio.anytype.presentation.editor.picker.IconPickerViewModel
|
||||
import com.anytypeio.anytype.presentation.editor.picker.IconPickerViewModel.ViewState
|
||||
import com.google.android.material.snackbar.Snackbar
|
||||
import timber.log.Timber
|
||||
import javax.inject.Inject
|
||||
|
||||
abstract class ObjectIconPickerBaseFragment : BaseBottomSheetTextInputFragment<FragmentPageIconPickerBinding>() {
|
||||
abstract class IconPickerFragmentBase<T> :
|
||||
BaseBottomSheetTextInputFragment<FragmentPageIconPickerBinding>() {
|
||||
|
||||
protected val target: String
|
||||
get() = requireArguments()
|
||||
.getString(ARG_TARGET_ID_KEY)
|
||||
?: throw IllegalStateException(MISSING_TARGET_ERROR)
|
||||
protected val context: Id
|
||||
get() = arg(ARG_CONTEXT_ID_KEY)
|
||||
|
||||
protected val context: String
|
||||
get() = requireArguments()
|
||||
.getString(ARG_CONTEXT_ID_KEY)
|
||||
?: throw IllegalStateException(MISSING_CONTEXT_ERROR)
|
||||
/**
|
||||
* The target for which we choose icon
|
||||
* i.e. Object, callout text block
|
||||
*/
|
||||
protected abstract val target: T
|
||||
|
||||
abstract val vm : ObjectIconPickerBaseViewModel
|
||||
abstract val vm: IconPickerViewModel<T>
|
||||
|
||||
private val emojiPickerAdapter by lazy {
|
||||
DocumentEmojiIconPickerAdapter(
|
||||
|
@ -57,8 +53,7 @@ abstract class ObjectIconPickerBaseFragment : BaseBottomSheetTextInputFragment<F
|
|||
onEmojiClicked = { unicode ->
|
||||
vm.onEmojiClicked(
|
||||
unicode = unicode,
|
||||
target = target,
|
||||
context = context
|
||||
iconable = target
|
||||
)
|
||||
}
|
||||
)
|
||||
|
@ -75,8 +70,8 @@ abstract class ObjectIconPickerBaseFragment : BaseBottomSheetTextInputFragment<F
|
|||
clearSearchText.invisible()
|
||||
}
|
||||
filterInputField.doAfterTextChanged { vm.onQueryChanged(it.toString()) }
|
||||
btnRemoveIcon.setOnClickListener { vm.onRemoveClicked(context) }
|
||||
tvTabRandom.setOnClickListener { vm.onRandomEmoji(ctx = context, target = target) }
|
||||
btnRemoveIcon.setOnClickListener { vm.onRemoveClicked(target) }
|
||||
tvTabRandom.setOnClickListener { vm.onRandomEmoji(target) }
|
||||
tvTabUpload.setOnClickListener { proceedWithImagePick() }
|
||||
}
|
||||
skipCollapsed()
|
||||
|
@ -160,12 +155,12 @@ abstract class ObjectIconPickerBaseFragment : BaseBottomSheetTextInputFragment<F
|
|||
}
|
||||
}
|
||||
|
||||
val getContent = registerForActivityResult(GetImageContract()) { uri: Uri? ->
|
||||
private val getContent = registerForActivityResult(GetImageContract()) { uri: Uri? ->
|
||||
if (uri != null) {
|
||||
try {
|
||||
val path = uri.parseImagePath(requireContext())
|
||||
vm.onPickedFromDevice(
|
||||
ctx = context,
|
||||
iconable = target,
|
||||
path = path
|
||||
)
|
||||
} catch (e: Exception) {
|
||||
|
@ -193,39 +188,12 @@ abstract class ObjectIconPickerBaseFragment : BaseBottomSheetTextInputFragment<F
|
|||
private const val EMPTY_FILTER_TEXT = ""
|
||||
private const val PAGE_ICON_PICKER_DEFAULT_SPAN_COUNT = 6
|
||||
private const val EMOJI_RECYCLER_ITEM_VIEW_CACHE_SIZE = 2000
|
||||
private const val MISSING_TARGET_ERROR = "Missing target id"
|
||||
private const val MISSING_CONTEXT_ERROR = "Missing context id"
|
||||
private const val UNEXPECTED_VIEW_TYPE_MESSAGE = "Unexpected view type"
|
||||
|
||||
const val ARG_CONTEXT_ID_KEY = "arg.picker.context.id"
|
||||
const val ARG_TARGET_ID_KEY = "arg.picker.target.id"
|
||||
|
||||
private const val SELECT_IMAGE_CODE = 1
|
||||
private const val COULD_NOT_PARSE_PATH_ERROR = "Could not parse path to your image"
|
||||
private const val REQUEST_PERMISSION_CODE = 2
|
||||
}
|
||||
}
|
||||
|
||||
open class ObjectIconPickerFragment : ObjectIconPickerBaseFragment() {
|
||||
|
||||
@Inject
|
||||
lateinit var factory: ObjectIconPickerViewModelFactory
|
||||
override val vm by viewModels<ObjectIconPickerViewModel> { factory }
|
||||
|
||||
override fun injectDependencies() {
|
||||
componentManager().objectIconPickerComponent.get(context).inject(this)
|
||||
}
|
||||
|
||||
override fun releaseDependencies() {
|
||||
componentManager().objectIconPickerComponent.release(context)
|
||||
}
|
||||
|
||||
companion object {
|
||||
fun new(context: String, target: String) = ObjectIconPickerFragment().apply {
|
||||
arguments = bundleOf(
|
||||
ARG_CONTEXT_ID_KEY to context,
|
||||
ARG_TARGET_ID_KEY to target
|
||||
)
|
||||
}
|
||||
}
|
||||
}
|
|
@ -0,0 +1,35 @@
|
|||
package com.anytypeio.anytype.ui.editor.modals
|
||||
|
||||
import androidx.core.os.bundleOf
|
||||
import androidx.fragment.app.viewModels
|
||||
import com.anytypeio.anytype.core_models.Id
|
||||
import com.anytypeio.anytype.di.common.componentManager
|
||||
import com.anytypeio.anytype.presentation.editor.picker.IconPickerViewModel
|
||||
import com.anytypeio.anytype.presentation.editor.picker.ObjectIconPickerViewModelFactory
|
||||
import javax.inject.Inject
|
||||
|
||||
open class ObjectIconPickerFragment : IconPickerFragmentBase<Id>() {
|
||||
|
||||
@Inject
|
||||
lateinit var factory: ObjectIconPickerViewModelFactory
|
||||
override val vm by viewModels<IconPickerViewModel<Id>> { factory }
|
||||
|
||||
override val target: Id
|
||||
get() = context
|
||||
|
||||
override fun injectDependencies() {
|
||||
componentManager().objectIconPickerComponent.get(context).inject(this)
|
||||
}
|
||||
|
||||
override fun releaseDependencies() {
|
||||
componentManager().objectIconPickerComponent.release(context)
|
||||
}
|
||||
|
||||
companion object {
|
||||
fun new(context: String) = ObjectIconPickerFragment().apply {
|
||||
arguments = bundleOf(
|
||||
ARG_CONTEXT_ID_KEY to context,
|
||||
)
|
||||
}
|
||||
}
|
||||
}
|
|
@ -0,0 +1,46 @@
|
|||
package com.anytypeio.anytype.ui.editor.modals
|
||||
|
||||
import androidx.core.os.bundleOf
|
||||
import androidx.fragment.app.viewModels
|
||||
import com.anytypeio.anytype.core_models.Id
|
||||
import com.anytypeio.anytype.core_utils.ext.arg
|
||||
import com.anytypeio.anytype.di.common.componentManager
|
||||
import com.anytypeio.anytype.domain.icon.TextBlockTarget
|
||||
import com.anytypeio.anytype.presentation.editor.picker.IconPickerViewModel
|
||||
import com.anytypeio.anytype.presentation.editor.picker.TextBlockIconPickerViewModelFactory
|
||||
import javax.inject.Inject
|
||||
|
||||
class TextBlockIconPickerFragment : IconPickerFragmentBase<TextBlockTarget>() {
|
||||
|
||||
@Inject
|
||||
lateinit var factory: TextBlockIconPickerViewModelFactory
|
||||
override val vm by viewModels<IconPickerViewModel<TextBlockTarget>> { factory }
|
||||
|
||||
private val blockId: Id
|
||||
get() = arg(ARG_BLOCK_ID_KEY)
|
||||
|
||||
override val target: TextBlockTarget by lazy {
|
||||
TextBlockTarget(context, blockId)
|
||||
}
|
||||
|
||||
override fun injectDependencies() {
|
||||
componentManager().textBlockIconPickerComponent.get(context).inject(this)
|
||||
}
|
||||
|
||||
override fun releaseDependencies() {
|
||||
componentManager().textBlockIconPickerComponent.release(context)
|
||||
}
|
||||
|
||||
companion object {
|
||||
const val ARG_BLOCK_ID_KEY = "arg.picker.block.id"
|
||||
fun new(
|
||||
context: Id,
|
||||
blockId: Id
|
||||
) = TextBlockIconPickerFragment().apply {
|
||||
arguments = bundleOf(
|
||||
ARG_CONTEXT_ID_KEY to context,
|
||||
ARG_BLOCK_ID_KEY to blockId
|
||||
)
|
||||
}
|
||||
}
|
||||
}
|
|
@ -22,7 +22,7 @@ import com.anytypeio.anytype.presentation.objects.menu.ObjectMenuViewModelBase
|
|||
import com.anytypeio.anytype.ui.editor.cover.SelectCoverObjectFragment
|
||||
import com.anytypeio.anytype.ui.editor.cover.SelectCoverObjectSetFragment
|
||||
import com.anytypeio.anytype.ui.editor.layout.ObjectLayoutFragment
|
||||
import com.anytypeio.anytype.ui.editor.modals.ObjectIconPickerBaseFragment
|
||||
import com.anytypeio.anytype.ui.editor.modals.IconPickerFragmentBase
|
||||
import com.anytypeio.anytype.ui.relations.RelationListFragment
|
||||
import kotlinx.coroutines.flow.launchIn
|
||||
import kotlinx.coroutines.flow.onEach
|
||||
|
@ -133,8 +133,7 @@ abstract class ObjectMenuBaseFragment : BaseBottomSheetFragment<FragmentObjectMe
|
|||
findNavController().navigate(
|
||||
R.id.objectIconPickerScreen,
|
||||
bundleOf(
|
||||
ObjectIconPickerBaseFragment.ARG_CONTEXT_ID_KEY to ctx,
|
||||
ObjectIconPickerBaseFragment.ARG_TARGET_ID_KEY to ctx,
|
||||
IconPickerFragmentBase.ARG_CONTEXT_ID_KEY to ctx,
|
||||
)
|
||||
)
|
||||
}
|
||||
|
@ -163,8 +162,7 @@ abstract class ObjectMenuBaseFragment : BaseBottomSheetFragment<FragmentObjectMe
|
|||
findNavController().navigate(
|
||||
R.id.objectSetIconPickerScreen,
|
||||
bundleOf(
|
||||
ObjectIconPickerBaseFragment.ARG_CONTEXT_ID_KEY to ctx,
|
||||
ObjectIconPickerBaseFragment.ARG_TARGET_ID_KEY to ctx,
|
||||
IconPickerFragmentBase.ARG_CONTEXT_ID_KEY to ctx,
|
||||
)
|
||||
)
|
||||
}
|
||||
|
|
|
@ -43,7 +43,16 @@ import com.anytypeio.anytype.core_ui.widgets.FeaturedRelationGroupWidget
|
|||
import com.anytypeio.anytype.core_ui.widgets.StatusBadgeWidget
|
||||
import com.anytypeio.anytype.core_ui.widgets.text.TextInputWidget
|
||||
import com.anytypeio.anytype.core_utils.OnSwipeListener
|
||||
import com.anytypeio.anytype.core_utils.ext.*
|
||||
import com.anytypeio.anytype.core_utils.ext.argString
|
||||
import com.anytypeio.anytype.core_utils.ext.dimen
|
||||
import com.anytypeio.anytype.core_utils.ext.drawable
|
||||
import com.anytypeio.anytype.core_utils.ext.gone
|
||||
import com.anytypeio.anytype.core_utils.ext.hideKeyboard
|
||||
import com.anytypeio.anytype.core_utils.ext.subscribe
|
||||
import com.anytypeio.anytype.core_utils.ext.syncFocusWithImeVisibility
|
||||
import com.anytypeio.anytype.core_utils.ext.syncTranslationWithImeVisibility
|
||||
import com.anytypeio.anytype.core_utils.ext.toast
|
||||
import com.anytypeio.anytype.core_utils.ext.visible
|
||||
import com.anytypeio.anytype.databinding.FragmentObjectSetBinding
|
||||
import com.anytypeio.anytype.di.common.componentManager
|
||||
import com.anytypeio.anytype.presentation.editor.cover.CoverColor
|
||||
|
@ -57,14 +66,18 @@ import com.anytypeio.anytype.presentation.sets.model.SortingExpression
|
|||
import com.anytypeio.anytype.presentation.sets.model.Viewer
|
||||
import com.anytypeio.anytype.ui.base.NavigationFragment
|
||||
import com.anytypeio.anytype.ui.editor.cover.SelectCoverObjectSetFragment
|
||||
import com.anytypeio.anytype.ui.editor.modals.ObjectIconPickerBaseFragment
|
||||
import com.anytypeio.anytype.ui.editor.modals.IconPickerFragmentBase
|
||||
import com.anytypeio.anytype.ui.editor.sheets.ObjectMenuBaseFragment
|
||||
import com.anytypeio.anytype.ui.relations.RelationDateValueFragment
|
||||
import com.anytypeio.anytype.ui.relations.RelationDateValueFragment.DateValueEditReceiver
|
||||
import com.anytypeio.anytype.ui.relations.RelationTextValueFragment
|
||||
import com.anytypeio.anytype.ui.relations.RelationTextValueFragment.TextValueEditReceiver
|
||||
import com.anytypeio.anytype.ui.relations.RelationValueBaseFragment
|
||||
import com.anytypeio.anytype.ui.sets.modals.*
|
||||
import com.anytypeio.anytype.ui.sets.modals.CreateDataViewViewerFragment
|
||||
import com.anytypeio.anytype.ui.sets.modals.EditDataViewViewerFragment
|
||||
import com.anytypeio.anytype.ui.sets.modals.ManageViewerFragment
|
||||
import com.anytypeio.anytype.ui.sets.modals.ViewerBottomSheetRootFragment
|
||||
import com.anytypeio.anytype.ui.sets.modals.ViewerRelationsFragment
|
||||
import com.anytypeio.anytype.ui.sets.modals.sort.ViewerSortFragment
|
||||
import com.bumptech.glide.Glide
|
||||
import kotlinx.coroutines.flow.filterNotNull
|
||||
|
@ -615,8 +628,7 @@ open class ObjectSetFragment :
|
|||
findNavController().navigate(
|
||||
R.id.action_objectSetScreen_to_objectSetIconPickerScreen,
|
||||
bundleOf(
|
||||
ObjectIconPickerBaseFragment.ARG_CONTEXT_ID_KEY to ctx,
|
||||
ObjectIconPickerBaseFragment.ARG_TARGET_ID_KEY to command.target
|
||||
IconPickerFragmentBase.ARG_CONTEXT_ID_KEY to ctx,
|
||||
)
|
||||
)
|
||||
}
|
||||
|
|
|
@ -1,17 +1,21 @@
|
|||
package com.anytypeio.anytype.ui.sets
|
||||
|
||||
import androidx.fragment.app.viewModels
|
||||
import com.anytypeio.anytype.core_models.Id
|
||||
import com.anytypeio.anytype.di.common.componentManager
|
||||
import com.anytypeio.anytype.presentation.editor.picker.ObjectSetIconPickerViewModel
|
||||
import com.anytypeio.anytype.presentation.editor.picker.IconPickerViewModel
|
||||
import com.anytypeio.anytype.presentation.editor.picker.ObjectSetIconPickerViewModelFactory
|
||||
import com.anytypeio.anytype.ui.editor.modals.ObjectIconPickerBaseFragment
|
||||
import com.anytypeio.anytype.ui.editor.modals.IconPickerFragmentBase
|
||||
import javax.inject.Inject
|
||||
|
||||
class ObjectSetIconPickerFragment : ObjectIconPickerBaseFragment() {
|
||||
class ObjectSetIconPickerFragment : IconPickerFragmentBase<Id>() {
|
||||
|
||||
@Inject
|
||||
lateinit var factory: ObjectSetIconPickerViewModelFactory
|
||||
override val vm by viewModels<ObjectSetIconPickerViewModel> { factory }
|
||||
override val vm by viewModels<IconPickerViewModel<Id>> { factory }
|
||||
|
||||
override val target: Id
|
||||
get() = context
|
||||
|
||||
override fun injectDependencies() {
|
||||
componentManager().objectSetIconPickerComponent.get(context).inject(this)
|
||||
|
|
|
@ -5,7 +5,7 @@
|
|||
android:layout_width="match_parent"
|
||||
android:layout_height="match_parent"
|
||||
android:orientation="vertical"
|
||||
tools:context="com.anytypeio.anytype.ui.editor.modals.ObjectIconPickerBaseFragment">
|
||||
tools:context="com.anytypeio.anytype.ui.editor.modals.IconPickerFragmentBase">
|
||||
|
||||
<FrameLayout
|
||||
android:layout_width="match_parent"
|
||||
|
|
|
@ -117,6 +117,24 @@ sealed class Command {
|
|||
val style: Block.Content.Text.Style
|
||||
)
|
||||
|
||||
/**
|
||||
* Command for set icon to text block
|
||||
* @property context context id
|
||||
* @property blockId text block id
|
||||
* @property icon
|
||||
*/
|
||||
data class SetTextIcon(
|
||||
val context: Id,
|
||||
val blockId: Id,
|
||||
val icon: Icon,
|
||||
) {
|
||||
sealed interface Icon {
|
||||
object None : Icon
|
||||
data class Emoji(val unicode: String) : Icon
|
||||
data class Image(val hash: Hash) : Icon
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Command for creating a block
|
||||
* @property context id of the context of the block (i.e. page, dashboard or something else)
|
||||
|
@ -250,12 +268,10 @@ sealed class Command {
|
|||
/**
|
||||
* Command for setting document's emoji icon
|
||||
* @property emoji emoji's unicode
|
||||
* @property target id of the target block (icon)
|
||||
* @property context id of the context for this operation
|
||||
*/
|
||||
data class SetDocumentEmojiIcon(
|
||||
val context: Id,
|
||||
val target: Id,
|
||||
val emoji: String
|
||||
)
|
||||
|
||||
|
|
|
@ -69,7 +69,9 @@ sealed class Event {
|
|||
val backgroundColor: String? = null,
|
||||
val marks: List<Text.Mark>? = null,
|
||||
val alignment: Block.Align? = null,
|
||||
val checked: Boolean? = null
|
||||
val checked: Boolean? = null,
|
||||
val emojiIcon: String? = null,
|
||||
val imageIcon: String? = null,
|
||||
) : Command()
|
||||
|
||||
/**
|
||||
|
|
|
@ -237,7 +237,10 @@ class BlockAdapter(
|
|||
|
||||
val holder = when (viewType) {
|
||||
HOLDER_PARAGRAPH -> {
|
||||
Paragraph(ItemBlockTextBinding.inflate(inflater, parent, false))
|
||||
Paragraph(
|
||||
ItemBlockTextBinding.inflate(inflater, parent, false),
|
||||
clicked = onClickListener
|
||||
)
|
||||
}
|
||||
HOLDER_TITLE -> {
|
||||
Title.Document(
|
||||
|
@ -369,17 +372,20 @@ class BlockAdapter(
|
|||
}
|
||||
HOLDER_HEADER_ONE -> {
|
||||
HeaderOne(
|
||||
binding = ItemBlockHeaderOneBinding.inflate(inflater, parent, false)
|
||||
binding = ItemBlockHeaderOneBinding.inflate(inflater, parent, false),
|
||||
clicked = onClickListener,
|
||||
)
|
||||
}
|
||||
HOLDER_HEADER_TWO -> {
|
||||
HeaderTwo(
|
||||
binding = ItemBlockHeaderTwoBinding.inflate(inflater, parent, false)
|
||||
binding = ItemBlockHeaderTwoBinding.inflate(inflater, parent, false),
|
||||
clicked = onClickListener,
|
||||
)
|
||||
}
|
||||
HOLDER_HEADER_THREE -> {
|
||||
HeaderThree(
|
||||
binding = ItemBlockHeaderThreeBinding.inflate(inflater, parent, false)
|
||||
binding = ItemBlockHeaderThreeBinding.inflate(inflater, parent, false),
|
||||
clicked = onClickListener,
|
||||
)
|
||||
}
|
||||
HOLDER_CODE_SNIPPET -> {
|
||||
|
@ -391,28 +397,28 @@ class BlockAdapter(
|
|||
Checkbox(
|
||||
binding = ItemBlockCheckboxBinding.inflate(
|
||||
inflater, parent, false
|
||||
)
|
||||
), clicked = onClickListener
|
||||
)
|
||||
}
|
||||
HOLDER_BULLET -> {
|
||||
Bulleted(
|
||||
binding = ItemBlockBulletedBinding.inflate(
|
||||
inflater, parent, false
|
||||
)
|
||||
), clicked = onClickListener
|
||||
)
|
||||
}
|
||||
HOLDER_NUMBERED -> {
|
||||
Numbered(
|
||||
binding = ItemBlockNumberedBinding.inflate(
|
||||
inflater, parent, false
|
||||
)
|
||||
), clicked = onClickListener
|
||||
)
|
||||
}
|
||||
HOLDER_TOGGLE -> {
|
||||
Toggle(
|
||||
binding = ItemBlockToggleBinding.inflate(
|
||||
inflater, parent, false
|
||||
)
|
||||
), clicked = onClickListener
|
||||
)
|
||||
}
|
||||
HOLDER_DESCRIPTION -> {
|
||||
|
@ -624,11 +630,14 @@ class BlockAdapter(
|
|||
Highlight(
|
||||
binding = ItemBlockHighlightBinding.inflate(
|
||||
inflater, parent, false
|
||||
)
|
||||
), clicked = onClickListener
|
||||
)
|
||||
}
|
||||
HOLDER_CALLOUT -> {
|
||||
Callout(ItemBlockCalloutBinding.inflate(inflater, parent, false))
|
||||
Callout(
|
||||
binding = ItemBlockCalloutBinding.inflate(inflater, parent, false),
|
||||
clicked = onClickListener
|
||||
)
|
||||
}
|
||||
HOLDER_RELATION_DEFAULT -> {
|
||||
RelationViewHolder.Default(
|
||||
|
@ -724,9 +733,6 @@ class BlockAdapter(
|
|||
holder.content.setOnClickListener { view ->
|
||||
val pos = holder.bindingAdapterPosition
|
||||
if (pos != RecyclerView.NO_POSITION) {
|
||||
// if (view.hasFocus()) {
|
||||
// view.context.imm().showSoftInput(view, InputMethodManager.SHOW_FORCED)
|
||||
// }
|
||||
onTextInputClicked(blocks[pos].id)
|
||||
}
|
||||
}
|
||||
|
@ -738,11 +744,6 @@ class BlockAdapter(
|
|||
item.isFocused = hasFocus
|
||||
}
|
||||
onFocusChanged(item.id, hasFocus)
|
||||
// if (hasFocus) {
|
||||
// holder.content.context
|
||||
// .imm()
|
||||
// .showSoftInput(holder.content, InputMethodManager.SHOW_FORCED)
|
||||
// }
|
||||
}
|
||||
}
|
||||
holder.content.selectionWatcher = { selection ->
|
||||
|
@ -1141,14 +1142,11 @@ class BlockAdapter(
|
|||
onTextBlockTextChanged(item)
|
||||
}
|
||||
},
|
||||
onSelectionChanged = onSelectionChanged,
|
||||
clicked = onClickListener,
|
||||
onMentionEvent = onMentionEvent,
|
||||
onSlashEvent = onSlashEvent,
|
||||
onEmptyBlockBackspaceClicked = onEmptyBlockBackspaceClicked,
|
||||
onSplitLineEnterClicked = onSplitLineEnterClicked,
|
||||
onNonEmptyBlockBackspaceClicked = onNonEmptyBlockBackspaceClicked,
|
||||
onTextInputClicked = onTextInputClicked,
|
||||
onBackPressedCallback = onBackPressedCallback
|
||||
)
|
||||
}
|
||||
|
@ -1156,7 +1154,6 @@ class BlockAdapter(
|
|||
holder.bind(
|
||||
block = blocks[position] as BlockView.Text.Header.One,
|
||||
onTextBlockTextChanged = onTextBlockTextChanged,
|
||||
clicked = onClickListener,
|
||||
onMentionEvent = onMentionEvent,
|
||||
onSlashEvent = onSlashEvent,
|
||||
onEmptyBlockBackspaceClicked = onEmptyBlockBackspaceClicked,
|
||||
|
@ -1169,7 +1166,6 @@ class BlockAdapter(
|
|||
holder.bind(
|
||||
block = blocks[position] as BlockView.Text.Header.Two,
|
||||
onTextBlockTextChanged = onTextBlockTextChanged,
|
||||
clicked = onClickListener,
|
||||
onMentionEvent = onMentionEvent,
|
||||
onSlashEvent = onSlashEvent,
|
||||
onEmptyBlockBackspaceClicked = onEmptyBlockBackspaceClicked,
|
||||
|
@ -1182,7 +1178,6 @@ class BlockAdapter(
|
|||
holder.bind(
|
||||
block = blocks[position] as BlockView.Text.Header.Three,
|
||||
onTextBlockTextChanged = onTextBlockTextChanged,
|
||||
clicked = onClickListener,
|
||||
onMentionEvent = onMentionEvent,
|
||||
onSlashEvent = onSlashEvent,
|
||||
onEmptyBlockBackspaceClicked = onEmptyBlockBackspaceClicked,
|
||||
|
@ -1196,14 +1191,11 @@ class BlockAdapter(
|
|||
item = blocks[position] as BlockView.Text.Checkbox,
|
||||
onTextBlockTextChanged = onTextBlockTextChanged,
|
||||
onCheckboxClicked = onCheckboxClicked,
|
||||
onSelectionChanged = onSelectionChanged,
|
||||
clicked = onClickListener,
|
||||
onMentionEvent = onMentionEvent,
|
||||
onSlashEvent = onSlashEvent,
|
||||
onEmptyBlockBackspaceClicked = onEmptyBlockBackspaceClicked,
|
||||
onSplitLineEnterClicked = onSplitLineEnterClicked,
|
||||
onNonEmptyBlockBackspaceClicked = onNonEmptyBlockBackspaceClicked,
|
||||
onTextInputClicked = onTextInputClicked,
|
||||
onBackPressedCallback = onBackPressedCallback
|
||||
)
|
||||
}
|
||||
|
@ -1211,7 +1203,6 @@ class BlockAdapter(
|
|||
holder.bind(
|
||||
item = blocks[position] as BlockView.Text.Bulleted,
|
||||
onTextBlockTextChanged = onTextBlockTextChanged,
|
||||
clicked = onClickListener,
|
||||
onMentionEvent = onMentionEvent,
|
||||
onSlashEvent = onSlashEvent,
|
||||
onEmptyBlockBackspaceClicked = onEmptyBlockBackspaceClicked,
|
||||
|
@ -1224,7 +1215,6 @@ class BlockAdapter(
|
|||
holder.bind(
|
||||
item = blocks[position] as BlockView.Text.Numbered,
|
||||
onTextBlockTextChanged = onTextBlockTextChanged,
|
||||
clicked = onClickListener,
|
||||
onMentionEvent = onMentionEvent,
|
||||
onSlashEvent = onSlashEvent,
|
||||
onEmptyBlockBackspaceClicked = onEmptyBlockBackspaceClicked,
|
||||
|
@ -1239,7 +1229,6 @@ class BlockAdapter(
|
|||
onTextBlockTextChanged = onTextBlockTextChanged,
|
||||
onTogglePlaceholderClicked = onTogglePlaceholderClicked,
|
||||
onToggleClicked = onToggleClicked,
|
||||
clicked = onClickListener,
|
||||
onMentionEvent = onMentionEvent,
|
||||
onSlashEvent = onSlashEvent,
|
||||
onEmptyBlockBackspaceClicked = onEmptyBlockBackspaceClicked,
|
||||
|
@ -1255,11 +1244,9 @@ class BlockAdapter(
|
|||
clicked = onClickListener,
|
||||
onMentionEvent = onMentionEvent,
|
||||
onSlashEvent = onSlashEvent,
|
||||
onSelectionChanged = onSelectionChanged,
|
||||
onEmptyBlockBackspaceClicked = onEmptyBlockBackspaceClicked,
|
||||
onSplitLineEnterClicked = onSplitLineEnterClicked,
|
||||
onNonEmptyBlockBackspaceClicked = onNonEmptyBlockBackspaceClicked,
|
||||
onTextInputClicked = onTextInputClicked,
|
||||
onBackPressedCallback = onBackPressedCallback
|
||||
)
|
||||
}
|
||||
|
@ -1267,7 +1254,6 @@ class BlockAdapter(
|
|||
holder.bind(
|
||||
item = blocks[position] as BlockView.Text.Callout,
|
||||
onTextBlockTextChanged = onTextBlockTextChanged,
|
||||
clicked = onClickListener,
|
||||
onMentionEvent = onMentionEvent,
|
||||
onSlashEvent = onSlashEvent,
|
||||
onEmptyBlockBackspaceClicked = onEmptyBlockBackspaceClicked,
|
||||
|
|
|
@ -20,8 +20,9 @@ import com.anytypeio.anytype.presentation.editor.editor.model.BlockView
|
|||
import com.anytypeio.anytype.presentation.editor.editor.slash.SlashEvent
|
||||
|
||||
class Bulleted(
|
||||
val binding: ItemBlockBulletedBinding
|
||||
) : Text(binding.root), SupportNesting {
|
||||
val binding: ItemBlockBulletedBinding,
|
||||
clicked: (ListenerType) -> Unit,
|
||||
) : Text(binding.root, clicked), SupportNesting {
|
||||
|
||||
val indent: View = binding.bulletIndent
|
||||
val bullet = binding.bullet
|
||||
|
@ -51,7 +52,6 @@ class Bulleted(
|
|||
fun bind(
|
||||
item: BlockView.Text.Bulleted,
|
||||
onTextBlockTextChanged: (BlockView.Text) -> Unit,
|
||||
clicked: (ListenerType) -> Unit,
|
||||
onMentionEvent: (MentionEvent) -> Unit,
|
||||
onSlashEvent: (SlashEvent) -> Unit,
|
||||
onSplitLineEnterClicked: (String, Editable, IntRange) -> Unit,
|
||||
|
@ -67,7 +67,6 @@ class Bulleted(
|
|||
}
|
||||
onTextBlockTextChanged(item)
|
||||
},
|
||||
clicked = clicked,
|
||||
onEmptyBlockBackspaceClicked = onEmptyBlockBackspaceClicked,
|
||||
onSplitLineEnterClicked = onSplitLineEnterClicked,
|
||||
onNonEmptyBlockBackspaceClicked = onNonEmptyBlockBackspaceClicked,
|
||||
|
|
|
@ -17,8 +17,12 @@ import com.anytypeio.anytype.presentation.editor.editor.model.BlockView
|
|||
import com.anytypeio.anytype.presentation.editor.editor.slash.SlashEvent
|
||||
|
||||
class Callout(
|
||||
val binding: ItemBlockCalloutBinding
|
||||
) : Text(binding.root), BlockViewHolder.IndentableHolder {
|
||||
val binding: ItemBlockCalloutBinding,
|
||||
clicked: (ListenerType) -> Unit,
|
||||
) : Text(
|
||||
view = binding.root,
|
||||
clicked = clicked
|
||||
), BlockViewHolder.IndentableHolder {
|
||||
|
||||
override val root: View = itemView
|
||||
override val content: TextInputWidget = binding.calloutText
|
||||
|
@ -48,7 +52,6 @@ class Callout(
|
|||
fun bind(
|
||||
item: BlockView.Text.Callout,
|
||||
onTextBlockTextChanged: (BlockView.Text) -> Unit,
|
||||
clicked: (ListenerType) -> Unit,
|
||||
onMentionEvent: (MentionEvent) -> Unit,
|
||||
onSlashEvent: (SlashEvent) -> Unit,
|
||||
onSplitLineEnterClicked: (String, Editable, IntRange) -> Unit,
|
||||
|
@ -64,13 +67,15 @@ class Callout(
|
|||
}
|
||||
onTextBlockTextChanged(item)
|
||||
},
|
||||
clicked = clicked,
|
||||
onEmptyBlockBackspaceClicked = onEmptyBlockBackspaceClicked,
|
||||
onSplitLineEnterClicked = onSplitLineEnterClicked,
|
||||
onNonEmptyBlockBackspaceClicked = onNonEmptyBlockBackspaceClicked,
|
||||
onBackPressedCallback = onBackPressedCallback
|
||||
).also {
|
||||
icon.setIcon(item.icon)
|
||||
icon.setOnClickListener {
|
||||
clicked(ListenerType.Callout.Icon(item.id))
|
||||
}
|
||||
setupMentionWatcher(onMentionEvent)
|
||||
setupSlashWatcher(onSlashEvent, item.getViewType())
|
||||
}
|
||||
|
|
|
@ -18,8 +18,9 @@ import com.anytypeio.anytype.presentation.editor.editor.model.BlockView
|
|||
import com.anytypeio.anytype.presentation.editor.editor.slash.SlashEvent
|
||||
|
||||
class Checkbox(
|
||||
val binding: ItemBlockCheckboxBinding
|
||||
) : Text(binding.root), SupportNesting {
|
||||
val binding: ItemBlockCheckboxBinding,
|
||||
clicked: (ListenerType) -> Unit,
|
||||
) : Text(binding.root, clicked), SupportNesting {
|
||||
|
||||
var mode = BlockView.Mode.EDIT
|
||||
|
||||
|
@ -51,14 +52,11 @@ class Checkbox(
|
|||
item: BlockView.Text.Checkbox,
|
||||
onTextBlockTextChanged: (BlockView.Text) -> Unit,
|
||||
onCheckboxClicked: (BlockView.Text.Checkbox) -> Unit,
|
||||
onSelectionChanged: (String, IntRange) -> Unit,
|
||||
clicked: (ListenerType) -> Unit,
|
||||
onMentionEvent: (MentionEvent) -> Unit,
|
||||
onSlashEvent: (SlashEvent) -> Unit,
|
||||
onSplitLineEnterClicked: (String, Editable, IntRange) -> Unit,
|
||||
onEmptyBlockBackspaceClicked: (String) -> Unit,
|
||||
onNonEmptyBlockBackspaceClicked: (String, Editable) -> Unit,
|
||||
onTextInputClicked: (String) -> Unit,
|
||||
onBackPressedCallback: () -> Boolean
|
||||
) = super.bind(
|
||||
item = item,
|
||||
|
@ -69,7 +67,6 @@ class Checkbox(
|
|||
}
|
||||
onTextBlockTextChanged(item)
|
||||
},
|
||||
clicked = clicked,
|
||||
onEmptyBlockBackspaceClicked = onEmptyBlockBackspaceClicked,
|
||||
onSplitLineEnterClicked = onSplitLineEnterClicked,
|
||||
onNonEmptyBlockBackspaceClicked = onNonEmptyBlockBackspaceClicked,
|
||||
|
|
|
@ -15,15 +15,15 @@ import com.anytypeio.anytype.presentation.editor.editor.model.BlockView
|
|||
import com.anytypeio.anytype.presentation.editor.editor.slash.SlashEvent
|
||||
|
||||
abstract class Header(
|
||||
view: View
|
||||
) : Text(view), TextBlockHolder, BlockViewHolder.IndentableHolder {
|
||||
view: View,
|
||||
clicked: (ListenerType) -> Unit,
|
||||
) : Text(view, clicked), TextBlockHolder, BlockViewHolder.IndentableHolder {
|
||||
|
||||
abstract val header: TextInputWidget
|
||||
|
||||
fun bind(
|
||||
block: BlockView.Text.Header,
|
||||
onTextBlockTextChanged: (BlockView.Text) -> Unit,
|
||||
clicked: (ListenerType) -> Unit,
|
||||
onMentionEvent: (MentionEvent) -> Unit,
|
||||
onSlashEvent: (SlashEvent) -> Unit,
|
||||
onSplitLineEnterClicked: (String, Editable, IntRange) -> Unit,
|
||||
|
@ -39,7 +39,6 @@ abstract class Header(
|
|||
}
|
||||
onTextBlockTextChanged(block)
|
||||
},
|
||||
clicked = clicked,
|
||||
onEmptyBlockBackspaceClicked = onEmptyBlockBackspaceClicked,
|
||||
onSplitLineEnterClicked = onSplitLineEnterClicked,
|
||||
onNonEmptyBlockBackspaceClicked = onNonEmptyBlockBackspaceClicked,
|
||||
|
|
|
@ -6,10 +6,12 @@ import androidx.core.content.ContextCompat
|
|||
import com.anytypeio.anytype.core_ui.R
|
||||
import com.anytypeio.anytype.core_ui.databinding.ItemBlockHeaderOneBinding
|
||||
import com.anytypeio.anytype.core_ui.widgets.text.TextInputWidget
|
||||
import com.anytypeio.anytype.presentation.editor.editor.listener.ListenerType
|
||||
|
||||
class HeaderOne(
|
||||
val binding: ItemBlockHeaderOneBinding
|
||||
) : Header(binding.root) {
|
||||
val binding: ItemBlockHeaderOneBinding,
|
||||
clicked: (ListenerType) -> Unit,
|
||||
) : Header(binding.root, clicked) {
|
||||
|
||||
override val header: TextInputWidget = binding.headerOne
|
||||
override val content: TextInputWidget get() = header
|
||||
|
|
|
@ -6,10 +6,12 @@ import androidx.core.content.ContextCompat
|
|||
import com.anytypeio.anytype.core_ui.R
|
||||
import com.anytypeio.anytype.core_ui.databinding.ItemBlockHeaderThreeBinding
|
||||
import com.anytypeio.anytype.core_ui.widgets.text.TextInputWidget
|
||||
import com.anytypeio.anytype.presentation.editor.editor.listener.ListenerType
|
||||
|
||||
class HeaderThree(
|
||||
val binding: ItemBlockHeaderThreeBinding
|
||||
) : Header(binding.root) {
|
||||
val binding: ItemBlockHeaderThreeBinding,
|
||||
clicked: (ListenerType) -> Unit,
|
||||
) : Header(binding.root, clicked) {
|
||||
|
||||
override val header: TextInputWidget = binding.headerThree
|
||||
override val content: TextInputWidget get() = header
|
||||
|
|
|
@ -6,10 +6,12 @@ import androidx.core.content.ContextCompat
|
|||
import com.anytypeio.anytype.core_ui.R
|
||||
import com.anytypeio.anytype.core_ui.databinding.ItemBlockHeaderTwoBinding
|
||||
import com.anytypeio.anytype.core_ui.widgets.text.TextInputWidget
|
||||
import com.anytypeio.anytype.presentation.editor.editor.listener.ListenerType
|
||||
|
||||
class HeaderTwo(
|
||||
val binding: ItemBlockHeaderTwoBinding
|
||||
) : Header(binding.root) {
|
||||
val binding: ItemBlockHeaderTwoBinding,
|
||||
clicked: (ListenerType) -> Unit,
|
||||
) : Header(binding.root, clicked) {
|
||||
|
||||
override val header: TextInputWidget = binding.headerTwo
|
||||
override val content: TextInputWidget get() = header
|
||||
|
|
|
@ -14,8 +14,6 @@ import com.anytypeio.anytype.core_ui.features.editor.BlockViewHolder
|
|||
import com.anytypeio.anytype.core_ui.features.editor.SupportNesting
|
||||
import com.anytypeio.anytype.core_ui.features.editor.decoration.DecoratableViewHolder
|
||||
import com.anytypeio.anytype.core_ui.features.editor.decoration.EditorDecorationContainer
|
||||
import com.anytypeio.anytype.core_ui.features.editor.decoration.OffsetBottom
|
||||
import com.anytypeio.anytype.core_ui.features.editor.decoration.OffsetLeft
|
||||
import com.anytypeio.anytype.core_ui.features.editor.marks
|
||||
import com.anytypeio.anytype.core_ui.tools.DefaultSpannableFactory
|
||||
import com.anytypeio.anytype.core_ui.widgets.text.TextInputWidget
|
||||
|
@ -26,8 +24,9 @@ import com.anytypeio.anytype.presentation.editor.editor.model.BlockView
|
|||
import com.anytypeio.anytype.presentation.editor.editor.slash.SlashEvent
|
||||
|
||||
class Highlight(
|
||||
val binding: ItemBlockHighlightBinding
|
||||
) : Text(binding.root), BlockViewHolder.IndentableHolder, SupportNesting, DecoratableViewHolder {
|
||||
val binding: ItemBlockHighlightBinding,
|
||||
clicked: (ListenerType) -> Unit,
|
||||
) : Text(binding.root, clicked), BlockViewHolder.IndentableHolder, SupportNesting, DecoratableViewHolder {
|
||||
|
||||
override val content: TextInputWidget = binding.highlightContent
|
||||
override val root: View = itemView
|
||||
|
@ -78,14 +77,12 @@ class Highlight(
|
|||
fun bind(
|
||||
item: BlockView.Text.Highlight,
|
||||
onTextBlockTextChanged: (BlockView.Text) -> Unit,
|
||||
onSelectionChanged: (String, IntRange) -> Unit,
|
||||
clicked: (ListenerType) -> Unit,
|
||||
onMentionEvent: (MentionEvent) -> Unit,
|
||||
onSlashEvent: (SlashEvent) -> Unit,
|
||||
onSplitLineEnterClicked: (String, Editable, IntRange) -> Unit,
|
||||
onEmptyBlockBackspaceClicked: (String) -> Unit,
|
||||
onNonEmptyBlockBackspaceClicked: (String, Editable) -> Unit,
|
||||
onTextInputClicked: (String) -> Unit,
|
||||
onBackPressedCallback: () -> Boolean
|
||||
) = super.bind(
|
||||
item = item,
|
||||
|
@ -96,7 +93,6 @@ class Highlight(
|
|||
}
|
||||
onTextBlockTextChanged(item)
|
||||
},
|
||||
clicked = clicked,
|
||||
onEmptyBlockBackspaceClicked = onEmptyBlockBackspaceClicked,
|
||||
onSplitLineEnterClicked = onSplitLineEnterClicked,
|
||||
onNonEmptyBlockBackspaceClicked = onNonEmptyBlockBackspaceClicked,
|
||||
|
|
|
@ -16,15 +16,15 @@ import com.anytypeio.anytype.core_ui.features.editor.marks
|
|||
import com.anytypeio.anytype.core_ui.widgets.text.TextInputWidget
|
||||
import com.anytypeio.anytype.core_utils.ext.addDot
|
||||
import com.anytypeio.anytype.core_utils.ext.dimen
|
||||
import com.anytypeio.anytype.presentation.editor.editor.ThemeColor
|
||||
import com.anytypeio.anytype.presentation.editor.editor.listener.ListenerType
|
||||
import com.anytypeio.anytype.presentation.editor.editor.mention.MentionEvent
|
||||
import com.anytypeio.anytype.presentation.editor.editor.model.BlockView
|
||||
import com.anytypeio.anytype.presentation.editor.editor.slash.SlashEvent
|
||||
|
||||
class Numbered(
|
||||
val binding: ItemBlockNumberedBinding
|
||||
) : Text(binding.root), SupportNesting {
|
||||
val binding: ItemBlockNumberedBinding,
|
||||
clicked: (ListenerType) -> Unit,
|
||||
) : Text(binding.root, clicked), SupportNesting {
|
||||
|
||||
private val container = binding.numberedBlockContentContainer
|
||||
val number = binding.number
|
||||
|
@ -53,7 +53,6 @@ class Numbered(
|
|||
fun bind(
|
||||
item: BlockView.Text.Numbered,
|
||||
onTextBlockTextChanged: (BlockView.Text) -> Unit,
|
||||
clicked: (ListenerType) -> Unit,
|
||||
onMentionEvent: (MentionEvent) -> Unit,
|
||||
onSlashEvent: (SlashEvent) -> Unit,
|
||||
onSplitLineEnterClicked: (String, Editable, IntRange) -> Unit,
|
||||
|
@ -69,7 +68,6 @@ class Numbered(
|
|||
}
|
||||
onTextBlockTextChanged(item)
|
||||
},
|
||||
clicked = clicked,
|
||||
onEmptyBlockBackspaceClicked = onEmptyBlockBackspaceClicked,
|
||||
onSplitLineEnterClicked = onSplitLineEnterClicked,
|
||||
onNonEmptyBlockBackspaceClicked = onNonEmptyBlockBackspaceClicked,
|
||||
|
|
|
@ -22,8 +22,9 @@ import com.anytypeio.anytype.presentation.editor.editor.model.BlockView
|
|||
import com.anytypeio.anytype.presentation.editor.editor.slash.SlashEvent
|
||||
|
||||
class Paragraph(
|
||||
val binding: ItemBlockTextBinding
|
||||
) : Text(binding.root), SupportNesting, DecoratableViewHolder {
|
||||
val binding: ItemBlockTextBinding,
|
||||
clicked: (ListenerType) -> Unit,
|
||||
) : Text(binding.root, clicked), SupportNesting, DecoratableViewHolder {
|
||||
|
||||
override val root: View = binding.root
|
||||
override val content: TextInputWidget = binding.textContent
|
||||
|
@ -65,19 +66,15 @@ class Paragraph(
|
|||
fun bind(
|
||||
item: BlockView.Text.Paragraph,
|
||||
onTextChanged: (String, Editable) -> Unit,
|
||||
onSelectionChanged: (String, IntRange) -> Unit,
|
||||
clicked: (ListenerType) -> Unit,
|
||||
onMentionEvent: (MentionEvent) -> Unit,
|
||||
onSlashEvent: (SlashEvent) -> Unit,
|
||||
onSplitLineEnterClicked: (String, Editable, IntRange) -> Unit,
|
||||
onEmptyBlockBackspaceClicked: (String) -> Unit,
|
||||
onNonEmptyBlockBackspaceClicked: (String, Editable) -> Unit,
|
||||
onTextInputClicked: (String) -> Unit,
|
||||
onBackPressedCallback: () -> Boolean
|
||||
) = super.bind(
|
||||
item = item,
|
||||
onTextChanged = onTextChanged,
|
||||
clicked = clicked,
|
||||
onEmptyBlockBackspaceClicked = onEmptyBlockBackspaceClicked,
|
||||
onSplitLineEnterClicked = onSplitLineEnterClicked,
|
||||
onNonEmptyBlockBackspaceClicked = onNonEmptyBlockBackspaceClicked,
|
||||
|
|
|
@ -13,7 +13,8 @@ import com.anytypeio.anytype.presentation.editor.editor.model.BlockView
|
|||
import com.anytypeio.anytype.presentation.editor.editor.model.Checkable
|
||||
|
||||
abstract class Text(
|
||||
view: View
|
||||
view: View,
|
||||
protected val clicked: (ListenerType) -> Unit,
|
||||
) : BlockViewHolder(view), TextBlockHolder, BlockViewHolder.IndentableHolder,
|
||||
BlockViewHolder.DragAndDropHolder {
|
||||
|
||||
|
@ -21,7 +22,6 @@ abstract class Text(
|
|||
|
||||
fun bind(
|
||||
item: BlockView.TextBlockProps,
|
||||
clicked: (ListenerType) -> Unit,
|
||||
onTextChanged: (String, Editable) -> Unit,
|
||||
onSplitLineEnterClicked: (String, Editable, IntRange) -> Unit,
|
||||
onEmptyBlockBackspaceClicked: (String) -> Unit,
|
||||
|
|
|
@ -18,8 +18,9 @@ import com.anytypeio.anytype.presentation.editor.editor.model.BlockView
|
|||
import com.anytypeio.anytype.presentation.editor.editor.slash.SlashEvent
|
||||
|
||||
class Toggle(
|
||||
val binding: ItemBlockToggleBinding
|
||||
) : Text(binding.root), SupportNesting {
|
||||
val binding: ItemBlockToggleBinding,
|
||||
clicked: (ListenerType) -> Unit,
|
||||
) : Text(binding.root, clicked), SupportNesting {
|
||||
|
||||
private var mode = BlockView.Mode.EDIT
|
||||
|
||||
|
@ -54,7 +55,6 @@ class Toggle(
|
|||
onTextBlockTextChanged: (BlockView.Text) -> Unit,
|
||||
onToggleClicked: (String) -> Unit,
|
||||
onTogglePlaceholderClicked: (String) -> Unit,
|
||||
clicked: (ListenerType) -> Unit,
|
||||
onMentionEvent: (MentionEvent) -> Unit,
|
||||
onSlashEvent: (SlashEvent) -> Unit,
|
||||
onSplitLineEnterClicked: (String, Editable, IntRange) -> Unit,
|
||||
|
@ -70,7 +70,6 @@ class Toggle(
|
|||
}
|
||||
onTextBlockTextChanged(item)
|
||||
},
|
||||
clicked = clicked,
|
||||
onEmptyBlockBackspaceClicked = onEmptyBlockBackspaceClicked,
|
||||
onSplitLineEnterClicked = onSplitLineEnterClicked,
|
||||
onNonEmptyBlockBackspaceClicked = onNonEmptyBlockBackspaceClicked,
|
||||
|
|
|
@ -11,12 +11,12 @@
|
|||
|
||||
<com.anytypeio.anytype.core_ui.widgets.ObjectIconWidget
|
||||
android:id="@+id/callout_icon"
|
||||
android:layout_width="20dp"
|
||||
android:layout_height="20dp"
|
||||
android:layout_width="24dp"
|
||||
android:layout_height="24dp"
|
||||
app:emojiSize="20dp"
|
||||
app:imageSize="20dp"
|
||||
android:layout_marginStart="20dp"
|
||||
android:layout_marginTop="20dp"
|
||||
android:layout_marginTop="18dp"
|
||||
android:padding="2dp"
|
||||
tools:background="@color/black" />
|
||||
|
||||
|
|
|
@ -9,7 +9,9 @@ import kotlinx.coroutines.flow.launchIn
|
|||
import kotlinx.coroutines.flow.onEach
|
||||
|
||||
inline fun <reified T> Fragment.arg(key: String): T {
|
||||
return requireArguments().get(key) as T
|
||||
return checkNotNull(requireArguments().get(key)) {
|
||||
"Fragment args missing value for $key"
|
||||
} as T
|
||||
}
|
||||
|
||||
inline fun <reified T> Fragment.argOrNull(key: String): T? {
|
||||
|
|
|
@ -28,16 +28,16 @@ import com.anytypeio.anytype.domain.page.Redo
|
|||
import com.anytypeio.anytype.domain.page.Undo
|
||||
|
||||
class BlockDataRepository(
|
||||
private val factory: BlockDataStoreFactory
|
||||
private val remote: BlockDataStore
|
||||
) : BlockRepository {
|
||||
|
||||
override suspend fun openDashboard(
|
||||
contextId: String,
|
||||
id: String
|
||||
) = factory.remote.openDashboard(id = id, contextId = contextId)
|
||||
) = remote.openDashboard(id = id, contextId = contextId)
|
||||
|
||||
override suspend fun openObjectPreview(id: Id): Result<Payload> = try {
|
||||
Result.Success(factory.remote.openObjectPreview(id))
|
||||
Result.Success(remote.openObjectPreview(id))
|
||||
} catch (e: BackwardCompatilityNotSupportedException) {
|
||||
Result.Failure(Error.BackwardCompatibility)
|
||||
} catch (e: NotFoundObjectException) {
|
||||
|
@ -45,7 +45,7 @@ class BlockDataRepository(
|
|||
}
|
||||
|
||||
override suspend fun openPage(id: String): Result<Payload> = try {
|
||||
Result.Success(factory.remote.openPage(id))
|
||||
Result.Success(remote.openPage(id))
|
||||
} catch (e: BackwardCompatilityNotSupportedException) {
|
||||
Result.Failure(Error.BackwardCompatibility)
|
||||
} catch (e: NotFoundObjectException) {
|
||||
|
@ -53,10 +53,10 @@ class BlockDataRepository(
|
|||
}
|
||||
|
||||
override suspend fun openProfile(id: String): Payload =
|
||||
factory.remote.openProfile(id)
|
||||
remote.openProfile(id)
|
||||
|
||||
override suspend fun openObjectSet(id: String): Result<Payload> = try {
|
||||
Result.Success(factory.remote.openObjectSet(id))
|
||||
Result.Success(remote.openObjectSet(id))
|
||||
} catch (e: BackwardCompatilityNotSupportedException) {
|
||||
Result.Failure(Error.BackwardCompatibility)
|
||||
} catch (e: NotFoundObjectException) {
|
||||
|
@ -64,12 +64,12 @@ class BlockDataRepository(
|
|||
}
|
||||
|
||||
override suspend fun closeDashboard(id: String) {
|
||||
factory.remote.closeDashboard(id)
|
||||
remote.closeDashboard(id)
|
||||
}
|
||||
|
||||
override suspend fun updateAlignment(
|
||||
command: Command.UpdateAlignment
|
||||
): Payload = factory.remote.updateAlignment(command)
|
||||
): Payload = remote.updateAlignment(command)
|
||||
|
||||
override suspend fun createPage(
|
||||
ctx: Id?,
|
||||
|
@ -77,7 +77,7 @@ class BlockDataRepository(
|
|||
isDraft: Boolean?,
|
||||
type: String?,
|
||||
template: Id?
|
||||
) = factory.remote.createPage(
|
||||
) = remote.createPage(
|
||||
ctx = ctx,
|
||||
emoji = emoji,
|
||||
isDraft = isDraft,
|
||||
|
@ -86,59 +86,62 @@ class BlockDataRepository(
|
|||
)
|
||||
|
||||
override suspend fun closePage(id: String) {
|
||||
factory.remote.closePage(id)
|
||||
remote.closePage(id)
|
||||
}
|
||||
|
||||
override suspend fun updateDocumentTitle(
|
||||
command: Command.UpdateTitle
|
||||
) = factory.remote.updateDocumentTitle(command)
|
||||
) = remote.updateDocumentTitle(command)
|
||||
|
||||
override suspend fun updateText(command: Command.UpdateText) {
|
||||
factory.remote.updateText(command)
|
||||
remote.updateText(command)
|
||||
}
|
||||
|
||||
override suspend fun updateTextStyle(
|
||||
command: Command.UpdateStyle
|
||||
): Payload = factory.remote.updateTextStyle(command)
|
||||
): Payload = remote.updateTextStyle(command)
|
||||
|
||||
override suspend fun setTextIcon(command: Command.SetTextIcon): Payload =
|
||||
remote.setTextIcon(command)
|
||||
|
||||
override suspend fun updateTextColor(
|
||||
command: Command.UpdateTextColor
|
||||
): Payload = factory.remote.updateTextColor(command)
|
||||
): Payload = remote.updateTextColor(command)
|
||||
|
||||
override suspend fun setLinkAppearance(command: Command.SetLinkAppearance): Payload {
|
||||
return factory.remote.setLinkAppearance(command)
|
||||
return remote.setLinkAppearance(command)
|
||||
}
|
||||
|
||||
override suspend fun updateBackgroundColor(
|
||||
command: Command.UpdateBackgroundColor
|
||||
): Payload = factory.remote.updateBackroundColor(command)
|
||||
): Payload = remote.updateBackroundColor(command)
|
||||
|
||||
override suspend fun updateCheckbox(
|
||||
command: Command.UpdateCheckbox
|
||||
): Payload = factory.remote.updateCheckbox(command)
|
||||
): Payload = remote.updateCheckbox(command)
|
||||
|
||||
override suspend fun create(command: Command.Create): Pair<Id, Payload> {
|
||||
return factory.remote.create(command).let { (id, payload) ->
|
||||
return remote.create(command).let { (id, payload) ->
|
||||
Pair(id, payload)
|
||||
}
|
||||
}
|
||||
|
||||
override suspend fun replace(
|
||||
command: Command.Replace
|
||||
): Pair<Id, Payload> = factory.remote.replace(command).let { (id, payload) ->
|
||||
): Pair<Id, Payload> = remote.replace(command).let { (id, payload) ->
|
||||
Pair(id, payload)
|
||||
}
|
||||
|
||||
override suspend fun duplicate(
|
||||
command: Command.Duplicate
|
||||
): Pair<List<Id>, Payload> = factory.remote.duplicate(command).let { (ids, payload) ->
|
||||
): Pair<List<Id>, Payload> = remote.duplicate(command).let { (ids, payload) ->
|
||||
Pair(ids, payload)
|
||||
}
|
||||
|
||||
override suspend fun createDocument(
|
||||
command: Command.CreateDocument
|
||||
): Triple<String, String, Payload> {
|
||||
return factory.remote.createDocument(
|
||||
return remote.createDocument(
|
||||
command
|
||||
).let { (id, target, payload) ->
|
||||
Triple(id, target, payload)
|
||||
|
@ -148,73 +151,73 @@ class BlockDataRepository(
|
|||
override suspend fun createNewDocument(
|
||||
command: Command.CreateNewDocument
|
||||
): Id {
|
||||
return factory.remote.createNewDocument(command)
|
||||
return remote.createNewDocument(command)
|
||||
}
|
||||
|
||||
override suspend fun move(command: Command.Move): Payload {
|
||||
return factory.remote.move(command)
|
||||
return remote.move(command)
|
||||
}
|
||||
|
||||
override suspend fun unlink(
|
||||
command: Command.Unlink
|
||||
): Payload = factory.remote.unlink(command)
|
||||
): Payload = remote.unlink(command)
|
||||
|
||||
override suspend fun merge(
|
||||
command: Command.Merge
|
||||
): Payload = factory.remote.merge(command)
|
||||
): Payload = remote.merge(command)
|
||||
|
||||
override suspend fun split(
|
||||
command: Command.Split
|
||||
): Pair<Id, Payload> = factory.remote.split(command).let { (id, payload) ->
|
||||
): Pair<Id, Payload> = remote.split(command).let { (id, payload) ->
|
||||
Pair(id, payload)
|
||||
}
|
||||
|
||||
override suspend fun setDocumentEmojiIcon(
|
||||
command: Command.SetDocumentEmojiIcon
|
||||
): Payload = factory.remote.setDocumentEmojiIcon(command)
|
||||
): Payload = remote.setDocumentEmojiIcon(command)
|
||||
|
||||
override suspend fun setDocumentImageIcon(
|
||||
command: Command.SetDocumentImageIcon
|
||||
): Payload = factory.remote.setDocumentImageIcon(command)
|
||||
): Payload = remote.setDocumentImageIcon(command)
|
||||
|
||||
override suspend fun setDocumentCoverColor(
|
||||
ctx: String,
|
||||
color: String
|
||||
): Payload = factory.remote.setDocumentCoverColor(ctx = ctx, color = color)
|
||||
): Payload = remote.setDocumentCoverColor(ctx = ctx, color = color)
|
||||
|
||||
override suspend fun setDocumentCoverGradient(
|
||||
ctx: String,
|
||||
gradient: String
|
||||
): Payload = factory.remote.setDocumentCoverGradient(ctx = ctx, gradient = gradient)
|
||||
): Payload = remote.setDocumentCoverGradient(ctx = ctx, gradient = gradient)
|
||||
|
||||
override suspend fun setDocumentCoverImage(
|
||||
ctx: String,
|
||||
hash: String
|
||||
): Payload = factory.remote.setDocumentCoverImage(ctx = ctx, hash = hash)
|
||||
): Payload = remote.setDocumentCoverImage(ctx = ctx, hash = hash)
|
||||
|
||||
override suspend fun removeDocumentCover(
|
||||
ctx: String
|
||||
): Payload = factory.remote.removeDocumentCover(ctx)
|
||||
): Payload = remote.removeDocumentCover(ctx)
|
||||
|
||||
override suspend fun removeDocumentIcon(
|
||||
ctx: Id
|
||||
): Payload = factory.remote.removeDocumentIcon(ctx)
|
||||
): Payload = remote.removeDocumentIcon(ctx)
|
||||
|
||||
override suspend fun setupBookmark(
|
||||
command: Command.SetupBookmark
|
||||
): Payload = factory.remote.setupBookmark(command)
|
||||
): Payload = remote.setupBookmark(command)
|
||||
|
||||
override suspend fun createBookmark(
|
||||
command: Command.CreateBookmark
|
||||
): Payload = factory.remote.createBookmark(command)
|
||||
): Payload = remote.createBookmark(command)
|
||||
|
||||
override suspend fun uploadBlock(command: Command.UploadBlock): Payload =
|
||||
factory.remote.uploadBlock(command)
|
||||
remote.uploadBlock(command)
|
||||
|
||||
override suspend fun undo(
|
||||
command: Command.Undo
|
||||
): Undo.Result = try {
|
||||
Undo.Result.Success(factory.remote.undo(command))
|
||||
Undo.Result.Success(remote.undo(command))
|
||||
} catch (e: UndoRedoExhaustedException) {
|
||||
Undo.Result.Exhausted
|
||||
}
|
||||
|
@ -222,43 +225,43 @@ class BlockDataRepository(
|
|||
override suspend fun redo(
|
||||
command: Command.Redo
|
||||
): Redo.Result = try {
|
||||
Redo.Result.Success(factory.remote.redo(command))
|
||||
Redo.Result.Success(remote.redo(command))
|
||||
} catch (e: UndoRedoExhaustedException) {
|
||||
Redo.Result.Exhausted
|
||||
}
|
||||
|
||||
override suspend fun turnIntoDocument(
|
||||
command: Command.TurnIntoDocument
|
||||
): List<Id> = factory.remote.turnIntoDocument(command)
|
||||
): List<Id> = remote.turnIntoDocument(command)
|
||||
|
||||
override suspend fun paste(
|
||||
command: Command.Paste
|
||||
): Response.Clipboard.Paste = factory.remote.paste(command)
|
||||
): Response.Clipboard.Paste = remote.paste(command)
|
||||
|
||||
override suspend fun copy(
|
||||
command: Command.Copy
|
||||
): Response.Clipboard.Copy = factory.remote.copy(command)
|
||||
): Response.Clipboard.Copy = remote.copy(command)
|
||||
|
||||
override suspend fun uploadFile(
|
||||
command: Command.UploadFile
|
||||
): Hash = factory.remote.uploadFile(command)
|
||||
): Hash = remote.uploadFile(command)
|
||||
|
||||
override suspend fun getObjectInfoWithLinks(
|
||||
pageId: String
|
||||
): ObjectInfoWithLinks = factory.remote.getObjectInfoWithLinks(pageId)
|
||||
): ObjectInfoWithLinks = remote.getObjectInfoWithLinks(pageId)
|
||||
|
||||
override suspend fun getListPages(): List<DocumentInfo> = factory.remote.getListPages()
|
||||
override suspend fun getListPages(): List<DocumentInfo> = remote.getListPages()
|
||||
|
||||
override suspend fun setRelationKey(command: Command.SetRelationKey): Payload =
|
||||
factory.remote.setRelationKey(command)
|
||||
remote.setRelationKey(command)
|
||||
|
||||
override suspend fun updateDivider(
|
||||
command: Command.UpdateDivider
|
||||
): Payload = factory.remote.updateDivider(command = command)
|
||||
): Payload = remote.updateDivider(command = command)
|
||||
|
||||
override suspend fun setFields(
|
||||
command: Command.SetFields
|
||||
): Payload = factory.remote.setFields(
|
||||
): Payload = remote.setFields(
|
||||
command = Command.SetFields(
|
||||
context = command.context,
|
||||
fields = command.fields.map { (id, fields) ->
|
||||
|
@ -271,19 +274,19 @@ class BlockDataRepository(
|
|||
context: Id,
|
||||
targets: List<Id>,
|
||||
style: Block.Content.Text.Style
|
||||
): Payload = factory.remote.turnInto(
|
||||
): Payload = remote.turnInto(
|
||||
context = context,
|
||||
targets = targets,
|
||||
style = style
|
||||
)
|
||||
|
||||
override suspend fun getObjectTypes(): List<ObjectType> {
|
||||
return factory.remote.getObjectTypes()
|
||||
return remote.getObjectTypes()
|
||||
}
|
||||
|
||||
override suspend fun createObjectType(
|
||||
prototype: ObjectType.Prototype
|
||||
): ObjectType = factory.remote.createObjectType(
|
||||
): ObjectType = remote.createObjectType(
|
||||
ObjectType.Prototype(
|
||||
name = prototype.name,
|
||||
emoji = prototype.emoji,
|
||||
|
@ -297,7 +300,7 @@ class BlockDataRepository(
|
|||
position: Position?,
|
||||
objectType: String?
|
||||
): CreateObjectSet.Response {
|
||||
val result = factory.remote.createSet(
|
||||
val result = remote.createSet(
|
||||
contextId = context,
|
||||
targetId = target,
|
||||
objectType = objectType,
|
||||
|
@ -316,7 +319,7 @@ class BlockDataRepository(
|
|||
view: Id,
|
||||
offset: Int,
|
||||
limit: Int
|
||||
): Payload = factory.remote.setActiveDataViewViewer(
|
||||
): Payload = remote.setActiveDataViewViewer(
|
||||
context = context,
|
||||
block = block,
|
||||
view = view,
|
||||
|
@ -330,7 +333,7 @@ class BlockDataRepository(
|
|||
name: String,
|
||||
format: Relation.Format,
|
||||
limitObjectTypes: List<Id>
|
||||
): Pair<Id, Payload> = factory.remote.addNewRelationToDataView(
|
||||
): Pair<Id, Payload> = remote.addNewRelationToDataView(
|
||||
context = context,
|
||||
target = target,
|
||||
name = name,
|
||||
|
@ -342,7 +345,7 @@ class BlockDataRepository(
|
|||
ctx: Id,
|
||||
dv: Id,
|
||||
relation: Id
|
||||
): Payload = factory.remote.addRelationToDataView(
|
||||
): Payload = remote.addRelationToDataView(
|
||||
ctx = ctx,
|
||||
dv = dv,
|
||||
relation = relation
|
||||
|
@ -352,7 +355,7 @@ class BlockDataRepository(
|
|||
ctx: Id,
|
||||
dv: Id,
|
||||
relation: Id
|
||||
): Payload = factory.remote.deleteRelationFromDataView(
|
||||
): Payload = remote.deleteRelationFromDataView(
|
||||
ctx = ctx,
|
||||
dv = dv,
|
||||
relation = relation
|
||||
|
@ -362,7 +365,7 @@ class BlockDataRepository(
|
|||
context: Id,
|
||||
target: Id,
|
||||
viewer: DVViewer
|
||||
): Payload = factory.remote.updateDataViewViewer(
|
||||
): Payload = remote.updateDataViewViewer(
|
||||
context = context,
|
||||
target = target,
|
||||
viewer = viewer
|
||||
|
@ -372,7 +375,7 @@ class BlockDataRepository(
|
|||
context: Id,
|
||||
target: Id,
|
||||
viewer: DVViewer
|
||||
): Payload = factory.remote.duplicateDataViewViewer(
|
||||
): Payload = remote.duplicateDataViewViewer(
|
||||
context = context,
|
||||
target = target,
|
||||
viewer = viewer
|
||||
|
@ -383,7 +386,7 @@ class BlockDataRepository(
|
|||
target: String,
|
||||
name: String,
|
||||
type: DVViewerType
|
||||
): Payload = factory.remote.addDataViewViewer(
|
||||
): Payload = remote.addDataViewViewer(
|
||||
ctx = ctx,
|
||||
target = target,
|
||||
name = name,
|
||||
|
@ -394,7 +397,7 @@ class BlockDataRepository(
|
|||
ctx: Id,
|
||||
dataview: Id,
|
||||
viewer: Id
|
||||
): Payload = factory.remote.removeDataViewViewer(
|
||||
): Payload = remote.removeDataViewViewer(
|
||||
ctx = ctx,
|
||||
dataview = dataview,
|
||||
viewer = viewer
|
||||
|
@ -405,7 +408,7 @@ class BlockDataRepository(
|
|||
target: Id,
|
||||
record: Id,
|
||||
values: Map<String, Any?>
|
||||
) = factory.remote.updateDataViewRecord(
|
||||
) = remote.updateDataViewRecord(
|
||||
context = context,
|
||||
target = target,
|
||||
record = record,
|
||||
|
@ -416,7 +419,7 @@ class BlockDataRepository(
|
|||
context: Id,
|
||||
target: Id,
|
||||
template: Id?
|
||||
): Map<String, Any?> = factory.remote.createDataViewRecord(
|
||||
): Map<String, Any?> = remote.createDataViewRecord(
|
||||
context = context,
|
||||
target = target,
|
||||
template = template
|
||||
|
@ -429,7 +432,7 @@ class BlockDataRepository(
|
|||
record: Id,
|
||||
name: Id,
|
||||
color: String
|
||||
): Pair<Payload, Id?> = factory.remote.addDataViewRelationOption(
|
||||
): Pair<Payload, Id?> = remote.addDataViewRelationOption(
|
||||
ctx = ctx,
|
||||
dataview = dataview,
|
||||
relation = relation,
|
||||
|
@ -443,7 +446,7 @@ class BlockDataRepository(
|
|||
relation: Id,
|
||||
name: String,
|
||||
color: String
|
||||
): Pair<Payload, Id?> = factory.remote.addObjectRelationOption(
|
||||
): Pair<Payload, Id?> = remote.addObjectRelationOption(
|
||||
ctx = ctx,
|
||||
relation = relation,
|
||||
name = name,
|
||||
|
@ -457,7 +460,7 @@ class BlockDataRepository(
|
|||
offset: Int,
|
||||
limit: Int,
|
||||
keys: List<Id>
|
||||
): List<Map<String, Any?>> = factory.remote.searchObjects(
|
||||
): List<Map<String, Any?>> = remote.searchObjects(
|
||||
sorts = sorts,
|
||||
filters = filters,
|
||||
fulltext = fulltext,
|
||||
|
@ -475,7 +478,7 @@ class BlockDataRepository(
|
|||
limit: Long,
|
||||
beforeId: Id?,
|
||||
afterId: Id?
|
||||
): SearchResult = factory.remote.searchObjectsWithSubscription(
|
||||
): SearchResult = remote.searchObjectsWithSubscription(
|
||||
subscription = subscription,
|
||||
sorts = sorts,
|
||||
filters = filters,
|
||||
|
@ -490,7 +493,7 @@ class BlockDataRepository(
|
|||
subscription: Id,
|
||||
ids: List<Id>,
|
||||
keys: List<String>
|
||||
): SearchResult = factory.remote.searchObjectsByIdWithSubscription(
|
||||
): SearchResult = remote.searchObjectsByIdWithSubscription(
|
||||
subscription = subscription,
|
||||
ids = ids,
|
||||
keys = keys
|
||||
|
@ -498,16 +501,16 @@ class BlockDataRepository(
|
|||
|
||||
override suspend fun cancelObjectSearchSubscription(
|
||||
subscriptions: List<Id>
|
||||
) = factory.remote.cancelObjectSearchSubscription(subscriptions)
|
||||
) = remote.cancelObjectSearchSubscription(subscriptions)
|
||||
|
||||
override suspend fun relationListAvailable(ctx: Id) = factory.remote.relationListAvailable(ctx)
|
||||
override suspend fun relationListAvailable(ctx: Id) = remote.relationListAvailable(ctx)
|
||||
|
||||
override suspend fun addRelationToObject(
|
||||
ctx: Id, relation: Id
|
||||
): Payload = factory.remote.addRelationToObject(ctx, relation)
|
||||
): Payload = remote.addRelationToObject(ctx, relation)
|
||||
|
||||
override suspend fun deleteRelationFromObject(ctx: Id, relation: Id): Payload {
|
||||
return factory.remote.deleteRelationFromObject(ctx = ctx, relation = relation)
|
||||
return remote.deleteRelationFromObject(ctx = ctx, relation = relation)
|
||||
}
|
||||
|
||||
override suspend fun addNewRelationToObject(
|
||||
|
@ -515,78 +518,78 @@ class BlockDataRepository(
|
|||
name: String,
|
||||
format: RelationFormat,
|
||||
limitObjectTypes: List<Id>
|
||||
): Pair<Id, Payload> = factory.remote.addNewRelationToObject(
|
||||
): Pair<Id, Payload> = remote.addNewRelationToObject(
|
||||
ctx = ctx,
|
||||
format = format,
|
||||
name = name,
|
||||
limitObjectTypes = limitObjectTypes
|
||||
)
|
||||
|
||||
override suspend fun debugSync(): String = factory.remote.debugSync()
|
||||
override suspend fun debugSync(): String = remote.debugSync()
|
||||
override suspend fun debugLocalStore(path: String): String =
|
||||
factory.remote.debugLocalStore(path)
|
||||
remote.debugLocalStore(path)
|
||||
|
||||
override suspend fun updateDetail(
|
||||
ctx: Id,
|
||||
key: String,
|
||||
value: Any?
|
||||
): Payload = factory.remote.updateDetail(
|
||||
): Payload = remote.updateDetail(
|
||||
ctx = ctx,
|
||||
key = key,
|
||||
value = value
|
||||
)
|
||||
|
||||
override suspend fun updateBlocksMark(command: Command.UpdateBlocksMark): Payload =
|
||||
factory.remote.updateBlocksMark(command)
|
||||
remote.updateBlocksMark(command)
|
||||
|
||||
override suspend fun addRelationToBlock(command: Command.AddRelationToBlock): Payload =
|
||||
factory.remote.addRelationToBlock(command)
|
||||
remote.addRelationToBlock(command)
|
||||
|
||||
override suspend fun setObjectTypeToObject(ctx: Id, typeId: Id): Payload =
|
||||
factory.remote.setObjectTypeToObject(ctx = ctx, typeId = typeId)
|
||||
remote.setObjectTypeToObject(ctx = ctx, typeId = typeId)
|
||||
|
||||
override suspend fun addToFeaturedRelations(
|
||||
ctx: Id,
|
||||
relations: List<Id>
|
||||
): Payload = factory.remote.addToFeaturedRelations(ctx, relations)
|
||||
): Payload = remote.addToFeaturedRelations(ctx, relations)
|
||||
|
||||
override suspend fun removeFromFeaturedRelations(
|
||||
ctx: Id,
|
||||
relations: List<Id>
|
||||
): Payload = factory.remote.removeFromFeaturedRelations(ctx, relations)
|
||||
): Payload = remote.removeFromFeaturedRelations(ctx, relations)
|
||||
|
||||
override suspend fun setObjectIsFavorite(
|
||||
ctx: Id,
|
||||
isFavorite: Boolean
|
||||
): Payload = factory.remote.setObjectIsFavorite(ctx = ctx, isFavorite = isFavorite)
|
||||
): Payload = remote.setObjectIsFavorite(ctx = ctx, isFavorite = isFavorite)
|
||||
|
||||
override suspend fun setObjectIsArchived(
|
||||
ctx: Id,
|
||||
isArchived: Boolean
|
||||
): Payload = factory.remote.setObjectIsArchived(ctx = ctx, isArchived = isArchived)
|
||||
): Payload = remote.setObjectIsArchived(ctx = ctx, isArchived = isArchived)
|
||||
|
||||
override suspend fun setObjectListIsArchived(
|
||||
targets: List<Id>,
|
||||
isArchived: Boolean
|
||||
) = factory.remote.setObjectListIsArchived(
|
||||
) = remote.setObjectListIsArchived(
|
||||
targets = targets,
|
||||
isArchived = isArchived
|
||||
)
|
||||
|
||||
override suspend fun deleteObjects(targets: List<Id>) =
|
||||
factory.remote.deleteObjects(targets = targets)
|
||||
remote.deleteObjects(targets = targets)
|
||||
|
||||
override suspend fun setObjectLayout(ctx: Id, layout: ObjectType.Layout): Payload =
|
||||
factory.remote.setObjectLayout(ctx, layout)
|
||||
remote.setObjectLayout(ctx, layout)
|
||||
|
||||
override suspend fun clearFileCache() = factory.remote.clearFileCache()
|
||||
override suspend fun clearFileCache() = remote.clearFileCache()
|
||||
|
||||
override suspend fun applyTemplate(ctx: Id, template: Id) = factory.remote.applyTemplate(
|
||||
override suspend fun applyTemplate(ctx: Id, template: Id) = remote.applyTemplate(
|
||||
ctx = ctx,
|
||||
template = template
|
||||
)
|
||||
|
||||
override suspend fun duplicateObject(id: Id): Id {
|
||||
return factory.remote.duplicateObject(id)
|
||||
return remote.duplicateObject(id)
|
||||
}
|
||||
}
|
|
@ -35,6 +35,7 @@ interface BlockDataStore {
|
|||
suspend fun updateDocumentTitle(command: Command.UpdateTitle)
|
||||
suspend fun updateText(command: Command.UpdateText)
|
||||
suspend fun updateTextStyle(command: Command.UpdateStyle): Payload
|
||||
suspend fun setTextIcon(command: Command.SetTextIcon): Payload
|
||||
|
||||
suspend fun setLinkAppearance(command: Command.SetLinkAppearance): Payload
|
||||
|
||||
|
|
|
@ -1,3 +0,0 @@
|
|||
package com.anytypeio.anytype.data.auth.repo.block
|
||||
|
||||
class BlockDataStoreFactory(val remote: BlockRemoteDataStore)
|
|
@ -34,6 +34,7 @@ interface BlockRemote {
|
|||
suspend fun updateDocumentTitle(command: Command.UpdateTitle)
|
||||
suspend fun updateText(command: Command.UpdateText)
|
||||
suspend fun updateTextStyle(command: Command.UpdateStyle) : Payload
|
||||
suspend fun setTextIcon(command: Command.SetTextIcon): Payload
|
||||
|
||||
suspend fun setLinkAppearance(command: Command.SetLinkAppearance): Payload
|
||||
|
||||
|
|
|
@ -67,6 +67,10 @@ class BlockRemoteDataStore(private val remote: BlockRemote) : BlockDataStore {
|
|||
command: Command.UpdateStyle
|
||||
): Payload = remote.updateTextStyle(command)
|
||||
|
||||
override suspend fun setTextIcon(command: Command.SetTextIcon): Payload {
|
||||
return remote.setTextIcon(command)
|
||||
}
|
||||
|
||||
override suspend fun updateTextColor(
|
||||
command: Command.UpdateTextColor
|
||||
): Payload = remote.updateTextColor(command)
|
||||
|
|
|
@ -75,6 +75,7 @@ interface BlockRepository {
|
|||
suspend fun updateDocumentTitle(command: Command.UpdateTitle)
|
||||
suspend fun updateText(command: Command.UpdateText)
|
||||
suspend fun updateTextStyle(command: Command.UpdateStyle): Payload
|
||||
suspend fun setTextIcon(command: Command.SetTextIcon): Payload
|
||||
suspend fun setLinkAppearance(command: Command.SetLinkAppearance): Payload
|
||||
|
||||
suspend fun updateTextColor(command: Command.UpdateTextColor): Payload
|
||||
|
|
|
@ -1,8 +1,6 @@
|
|||
package com.anytypeio.anytype.domain.icon
|
||||
|
||||
import com.anytypeio.anytype.core_models.Id
|
||||
import com.anytypeio.anytype.core_models.Payload
|
||||
import com.anytypeio.anytype.domain.base.BaseUseCase
|
||||
import com.anytypeio.anytype.domain.block.repo.BlockRepository
|
||||
|
||||
/**
|
||||
|
@ -10,17 +8,9 @@ import com.anytypeio.anytype.domain.block.repo.BlockRepository
|
|||
*/
|
||||
class RemoveDocumentIcon(
|
||||
private val repo: BlockRepository
|
||||
) : BaseUseCase<Payload, RemoveDocumentIcon.Params>() {
|
||||
) : RemoveIcon<Id>() {
|
||||
|
||||
override suspend fun run(params: Params) = safe {
|
||||
repo.removeDocumentIcon(params.ctx)
|
||||
override suspend fun run(params: Id) = safe {
|
||||
repo.removeDocumentIcon(params)
|
||||
}
|
||||
|
||||
/**
|
||||
* Params for for setting document's emoji icon
|
||||
* @property [ctx] id of the object, whose icon we need to remove.
|
||||
*/
|
||||
data class Params(
|
||||
val ctx: Id
|
||||
)
|
||||
}
|
|
@ -0,0 +1,6 @@
|
|||
package com.anytypeio.anytype.domain.icon
|
||||
|
||||
import com.anytypeio.anytype.core_models.Payload
|
||||
import com.anytypeio.anytype.domain.base.BaseUseCase
|
||||
|
||||
abstract class RemoveIcon<T> : BaseUseCase<Payload, T>()
|
|
@ -0,0 +1,22 @@
|
|||
package com.anytypeio.anytype.domain.icon
|
||||
|
||||
import com.anytypeio.anytype.core_models.Command
|
||||
import com.anytypeio.anytype.domain.block.repo.BlockRepository
|
||||
|
||||
/**
|
||||
* Remove text block icon i.e. callout block
|
||||
*/
|
||||
class RemoveTextBlockIcon(
|
||||
private val repo: BlockRepository
|
||||
) : RemoveIcon<TextBlockTarget>() {
|
||||
|
||||
override suspend fun run(params: TextBlockTarget) = safe {
|
||||
repo.setTextIcon(
|
||||
Command.SetTextIcon(
|
||||
context = params.context,
|
||||
blockId = params.blockId,
|
||||
icon = Command.SetTextIcon.Icon.None
|
||||
)
|
||||
)
|
||||
}
|
||||
}
|
|
@ -1,37 +1,22 @@
|
|||
package com.anytypeio.anytype.domain.icon
|
||||
|
||||
import com.anytypeio.anytype.domain.base.BaseUseCase
|
||||
import com.anytypeio.anytype.core_models.Command
|
||||
import com.anytypeio.anytype.domain.block.repo.BlockRepository
|
||||
import com.anytypeio.anytype.core_models.Id
|
||||
import com.anytypeio.anytype.core_models.Payload
|
||||
import com.anytypeio.anytype.domain.block.repo.BlockRepository
|
||||
|
||||
/**
|
||||
* Use-case for setting emoji icon.
|
||||
*/
|
||||
class SetDocumentEmojiIcon(
|
||||
private val repo: BlockRepository
|
||||
) : BaseUseCase<Payload, SetDocumentEmojiIcon.Params>() {
|
||||
) : SetEmojiIcon<Id>() {
|
||||
|
||||
override suspend fun run(params: Params) = safe {
|
||||
override suspend fun run(params: SetEmojiIcon.Params<Id>) = safe {
|
||||
repo.setDocumentEmojiIcon(
|
||||
command = Command.SetDocumentEmojiIcon(
|
||||
context = params.context,
|
||||
target = params.target,
|
||||
context = params.target,
|
||||
emoji = params.emoji
|
||||
)
|
||||
)
|
||||
}
|
||||
|
||||
/**
|
||||
* Params for for setting document's emoji icon
|
||||
* @property emoji emoji's unicode
|
||||
* @property target id of the target block (icon)
|
||||
* @property context id of the context for this operation
|
||||
*/
|
||||
data class Params(
|
||||
val emoji: String,
|
||||
val target: Id,
|
||||
val context: Id
|
||||
)
|
||||
}
|
|
@ -2,16 +2,14 @@ package com.anytypeio.anytype.domain.icon
|
|||
|
||||
import com.anytypeio.anytype.core_models.Block
|
||||
import com.anytypeio.anytype.core_models.Command
|
||||
import com.anytypeio.anytype.core_models.Hash
|
||||
import com.anytypeio.anytype.core_models.Payload
|
||||
import com.anytypeio.anytype.domain.base.BaseUseCase
|
||||
import com.anytypeio.anytype.core_models.Id
|
||||
import com.anytypeio.anytype.domain.block.repo.BlockRepository
|
||||
|
||||
class SetDocumentImageIcon(
|
||||
private val repo: BlockRepository
|
||||
) : BaseUseCase<Pair<Payload, Hash>, SetDocumentImageIcon.Params>() {
|
||||
) : SetImageIcon<Id>() {
|
||||
|
||||
override suspend fun run(params: Params) = safe {
|
||||
override suspend fun run(params: Params<Id>) = safe {
|
||||
val hash = repo.uploadFile(
|
||||
command = Command.UploadFile(
|
||||
path = params.path,
|
||||
|
@ -21,19 +19,9 @@ class SetDocumentImageIcon(
|
|||
val payload = repo.setDocumentImageIcon(
|
||||
command = Command.SetDocumentImageIcon(
|
||||
hash = hash,
|
||||
context = params.context
|
||||
context = params.target
|
||||
)
|
||||
)
|
||||
Pair(payload, hash)
|
||||
}
|
||||
|
||||
/**
|
||||
* Params for for setting document's image icon
|
||||
* @property path image path in file system
|
||||
* @property context id of the context for this operation
|
||||
*/
|
||||
class Params(
|
||||
val context: String,
|
||||
val path: String
|
||||
)
|
||||
}
|
|
@ -0,0 +1,17 @@
|
|||
package com.anytypeio.anytype.domain.icon
|
||||
|
||||
import com.anytypeio.anytype.core_models.Payload
|
||||
import com.anytypeio.anytype.domain.base.BaseUseCase
|
||||
|
||||
abstract class SetEmojiIcon<T> :
|
||||
BaseUseCase<Payload, SetEmojiIcon.Params<T>>() {
|
||||
|
||||
/**
|
||||
* @property emoji emoji's unicode
|
||||
* @property target i.e. object or text block
|
||||
*/
|
||||
data class Params<T>(
|
||||
val target: T,
|
||||
val emoji: String
|
||||
)
|
||||
}
|
|
@ -0,0 +1,17 @@
|
|||
package com.anytypeio.anytype.domain.icon
|
||||
|
||||
import com.anytypeio.anytype.core_models.Hash
|
||||
import com.anytypeio.anytype.core_models.Payload
|
||||
import com.anytypeio.anytype.domain.base.BaseUseCase
|
||||
|
||||
abstract class SetImageIcon<T> : BaseUseCase<Pair<Payload, Hash>, SetImageIcon.Params<T>>() {
|
||||
/**
|
||||
* Params for for setting document's image icon
|
||||
* @property path image path in file system
|
||||
* @property target i.e. id of the context or text blockId
|
||||
*/
|
||||
data class Params<T>(
|
||||
val target: T,
|
||||
val path: String
|
||||
)
|
||||
}
|
|
@ -0,0 +1,21 @@
|
|||
package com.anytypeio.anytype.domain.icon
|
||||
|
||||
import com.anytypeio.anytype.core_models.Command
|
||||
import com.anytypeio.anytype.domain.block.repo.BlockRepository
|
||||
|
||||
class SetTextBlockEmoji(
|
||||
private val repo: BlockRepository
|
||||
) : SetEmojiIcon<TextBlockTarget>() {
|
||||
|
||||
override suspend fun run(
|
||||
params: Params<TextBlockTarget>
|
||||
) = safe {
|
||||
repo.setTextIcon(
|
||||
command = Command.SetTextIcon(
|
||||
context = params.target.context,
|
||||
blockId = params.target.blockId,
|
||||
icon = Command.SetTextIcon.Icon.Emoji(params.emoji)
|
||||
)
|
||||
)
|
||||
}
|
||||
}
|
|
@ -0,0 +1,29 @@
|
|||
package com.anytypeio.anytype.domain.icon
|
||||
|
||||
import com.anytypeio.anytype.core_models.Block
|
||||
import com.anytypeio.anytype.core_models.Command
|
||||
import com.anytypeio.anytype.domain.block.repo.BlockRepository
|
||||
|
||||
class SetTextBlockImage(
|
||||
private val repo: BlockRepository
|
||||
) : SetImageIcon<TextBlockTarget>() {
|
||||
|
||||
override suspend fun run(
|
||||
params: Params<TextBlockTarget>
|
||||
) = safe {
|
||||
val hash = repo.uploadFile(
|
||||
command = Command.UploadFile(
|
||||
path = params.path,
|
||||
type = Block.Content.File.Type.IMAGE
|
||||
)
|
||||
)
|
||||
val payload = repo.setTextIcon(
|
||||
command = Command.SetTextIcon(
|
||||
icon = Command.SetTextIcon.Icon.Image(hash),
|
||||
context = params.target.context,
|
||||
blockId = params.target.blockId
|
||||
)
|
||||
)
|
||||
Pair(payload, hash)
|
||||
}
|
||||
}
|
|
@ -0,0 +1,8 @@
|
|||
package com.anytypeio.anytype.domain.icon
|
||||
|
||||
import com.anytypeio.anytype.core_models.Id
|
||||
|
||||
data class TextBlockTarget(
|
||||
val context: Id,
|
||||
val blockId: Id,
|
||||
)
|
|
@ -1,6 +1,5 @@
|
|||
package com.anytypeio.anytype.domain.auth
|
||||
|
||||
import com.anytypeio.anytype.core_models.Account
|
||||
import com.anytypeio.anytype.core_models.CoroutineTestRule
|
||||
import com.anytypeio.anytype.core_models.StubAccountSetup
|
||||
import com.anytypeio.anytype.domain.auth.interactor.CreateAccount
|
||||
|
|
|
@ -86,6 +86,10 @@ class BlockMiddleware(
|
|||
command: Command.UpdateStyle
|
||||
): Payload = middleware.blockTextListSetStyle(command)
|
||||
|
||||
override suspend fun setTextIcon(
|
||||
command: Command.SetTextIcon
|
||||
): Payload = middleware.blockTextSetIcon(command)
|
||||
|
||||
override suspend fun updateTextColor(
|
||||
command: Command.UpdateTextColor
|
||||
): Payload = middleware.blockTextListSetColor(command)
|
||||
|
@ -467,7 +471,8 @@ class BlockMiddleware(
|
|||
)
|
||||
|
||||
override suspend fun debugSync(): String = middleware.debugSync()
|
||||
override suspend fun debugLocalStore(path: String): String = middleware.debugExportLocalStore(path)
|
||||
override suspend fun debugLocalStore(path: String): String =
|
||||
middleware.debugExportLocalStore(path)
|
||||
|
||||
override suspend fun turnInto(
|
||||
context: String,
|
||||
|
|
|
@ -758,6 +758,25 @@ class Middleware(
|
|||
return response.event.toPayload()
|
||||
}
|
||||
|
||||
@Throws(Exception::class)
|
||||
fun blockTextSetIcon(command: Command.SetTextIcon): Payload {
|
||||
val (image, emoji) = when (val icon = command.icon) {
|
||||
is Command.SetTextIcon.Icon.Emoji -> "" to icon.unicode
|
||||
is Command.SetTextIcon.Icon.Image -> icon.hash to ""
|
||||
Command.SetTextIcon.Icon.None -> "" to ""
|
||||
}
|
||||
val request = Rpc.BlockText.SetIcon.Request(
|
||||
contextId = command.context,
|
||||
blockId = command.blockId,
|
||||
iconImage = image,
|
||||
iconEmoji = emoji,
|
||||
)
|
||||
if (BuildConfig.DEBUG) logRequest(request)
|
||||
val response = service.blockTextSetIcon(request)
|
||||
if (BuildConfig.DEBUG) logResponse(response)
|
||||
return response.event.toPayload()
|
||||
}
|
||||
|
||||
@Throws(Exception::class)
|
||||
fun blockTextSetChecked(
|
||||
context: String,
|
||||
|
|
|
@ -50,7 +50,9 @@ fun anytype.Event.Message.toCoreModels(
|
|||
style = event.style?.value_?.toCoreModels(),
|
||||
color = event.color?.value_,
|
||||
marks = event.marks?.value_?.marks?.map { it.toCoreModels() },
|
||||
checked = event.checked?.value_
|
||||
checked = event.checked?.value_,
|
||||
emojiIcon = event.iconEmoji?.value_,
|
||||
imageIcon = event.iconImage?.value_,
|
||||
)
|
||||
}
|
||||
blockSetBackgroundColor != null -> {
|
||||
|
|
|
@ -284,6 +284,9 @@ interface MiddlewareService {
|
|||
@Throws(Exception::class)
|
||||
fun blockTextListSetStyle(request: Rpc.BlockText.ListSetStyle.Request): Rpc.BlockText.ListSetStyle.Response
|
||||
|
||||
@Throws(Exception::class)
|
||||
fun blockTextSetIcon(request: Rpc.BlockText.SetIcon.Request): Rpc.BlockText.SetIcon.Response
|
||||
|
||||
//endregion
|
||||
|
||||
//region LINK BLOCK commands
|
||||
|
|
|
@ -487,6 +487,18 @@ class MiddlewareServiceImplementation : MiddlewareService {
|
|||
}
|
||||
}
|
||||
|
||||
override fun blockTextSetIcon(request: Rpc.BlockText.SetIcon.Request): Rpc.BlockText.SetIcon.Response {
|
||||
val encoded =
|
||||
Service.blockTextSetIcon(Rpc.BlockText.SetIcon.Request.ADAPTER.encode(request))
|
||||
val response = Rpc.BlockText.SetIcon.Response.ADAPTER.decode(encoded)
|
||||
val error = response.error
|
||||
if (error != null && error.code != Rpc.BlockText.SetIcon.Response.Error.Code.NULL) {
|
||||
throw Exception(error.description)
|
||||
} else {
|
||||
return response
|
||||
}
|
||||
}
|
||||
|
||||
override fun blockTextSetChecked(request: Rpc.BlockText.SetChecked.Request): Rpc.BlockText.SetChecked.Response {
|
||||
val encoded = Service.blockTextSetChecked(
|
||||
Rpc.BlockText.SetChecked.Request.ADAPTER.encode(request)
|
||||
|
|
|
@ -15,7 +15,12 @@ import org.junit.Before
|
|||
import org.junit.Test
|
||||
import org.mockito.Mock
|
||||
import org.mockito.MockitoAnnotations
|
||||
import org.mockito.kotlin.*
|
||||
import org.mockito.kotlin.any
|
||||
import org.mockito.kotlin.doReturn
|
||||
import org.mockito.kotlin.stub
|
||||
import org.mockito.kotlin.times
|
||||
import org.mockito.kotlin.verify
|
||||
import org.mockito.kotlin.verifyNoMoreInteractions
|
||||
import kotlin.test.assertEquals
|
||||
import kotlin.test.assertTrue
|
||||
|
||||
|
@ -213,7 +218,6 @@ class MiddlewareTest {
|
|||
|
||||
val command = Command.SetDocumentEmojiIcon(
|
||||
context = MockDataFactory.randomUuid(),
|
||||
target = MockDataFactory.randomUuid(),
|
||||
emoji = MockDataFactory.randomString()
|
||||
)
|
||||
|
||||
|
|
|
@ -49,7 +49,9 @@ class DocumentExternalEventReducer : StateReducer<List<Block>, Event> {
|
|||
text = event.text ?: content.text,
|
||||
marks = event.marks ?: content.marks,
|
||||
isChecked = event.checked ?: content.isChecked,
|
||||
align = event.alignment ?: content.align
|
||||
align = event.alignment ?: content.align,
|
||||
iconEmoji = event.emojiIcon ?: content.iconEmoji,
|
||||
iconImage = event.imageIcon ?: content.iconImage
|
||||
),
|
||||
backgroundColor = event.backgroundColor ?: block.backgroundColor,
|
||||
)
|
||||
|
|
|
@ -61,6 +61,7 @@ import com.anytypeio.anytype.domain.editor.Editor
|
|||
import com.anytypeio.anytype.domain.error.Error
|
||||
import com.anytypeio.anytype.domain.event.interactor.InterceptEvents
|
||||
import com.anytypeio.anytype.domain.icon.SetDocumentImageIcon
|
||||
import com.anytypeio.anytype.domain.icon.SetImageIcon
|
||||
import com.anytypeio.anytype.domain.launch.GetDefaultEditorType
|
||||
import com.anytypeio.anytype.domain.misc.UrlBuilder
|
||||
import com.anytypeio.anytype.domain.objects.SetObjectIsArchived
|
||||
|
@ -79,7 +80,6 @@ import com.anytypeio.anytype.presentation.common.StateReducer
|
|||
import com.anytypeio.anytype.presentation.common.SupportCommand
|
||||
import com.anytypeio.anytype.presentation.editor.ControlPanelMachine.Interactor
|
||||
import com.anytypeio.anytype.presentation.editor.Editor.Restore
|
||||
import com.anytypeio.anytype.presentation.editor.editor.BlockDimensions
|
||||
import com.anytypeio.anytype.presentation.editor.editor.Command
|
||||
import com.anytypeio.anytype.presentation.editor.editor.DetailModificationManager
|
||||
import com.anytypeio.anytype.presentation.editor.editor.Intent
|
||||
|
@ -380,8 +380,8 @@ class EditorViewModel(
|
|||
override fun onPickedDocImageFromDevice(ctx: Id, path: String) {
|
||||
viewModelScope.launch {
|
||||
setDocImageIcon(
|
||||
SetDocumentImageIcon.Params(
|
||||
context = ctx,
|
||||
SetImageIcon.Params(
|
||||
target = ctx,
|
||||
path = path
|
||||
)
|
||||
).process(
|
||||
|
@ -3657,6 +3657,9 @@ class EditorViewModel(
|
|||
else -> Unit
|
||||
}
|
||||
}
|
||||
is ListenerType.Callout.Icon -> {
|
||||
dispatch(Command.OpenTextBlockIconPicker(clicked.blockId))
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -3722,7 +3725,7 @@ class EditorViewModel(
|
|||
val isDetailsAllowed = restrictions.none { it == ObjectRestriction.DETAILS }
|
||||
if (isDetailsAllowed) {
|
||||
controlPanelInteractor.onEvent(ControlPanelMachine.Event.OnDocumentIconClicked)
|
||||
dispatch(Command.OpenDocumentEmojiIconPicker(target = context))
|
||||
dispatch(Command.OpenDocumentEmojiIconPicker)
|
||||
} else {
|
||||
sendToast(NOT_ALLOWED_FOR_OBJECT)
|
||||
}
|
||||
|
|
|
@ -9,9 +9,9 @@ sealed class Command {
|
|||
|
||||
data class OpenDocumentImagePicker(val mimeType: Mimetype) : Command()
|
||||
|
||||
data class OpenDocumentEmojiIconPicker(
|
||||
val target: String
|
||||
) : Command()
|
||||
object OpenDocumentEmojiIconPicker : Command()
|
||||
|
||||
data class OpenTextBlockIconPicker(val block: Id) : Command()
|
||||
|
||||
data class OpenGallery(
|
||||
val mimeType: Mimetype
|
||||
|
|
|
@ -5,57 +5,61 @@ import com.anytypeio.anytype.presentation.editor.editor.BlockDimensions
|
|||
import com.anytypeio.anytype.presentation.editor.editor.model.BlockView
|
||||
import com.anytypeio.anytype.presentation.relations.DocumentRelationView
|
||||
|
||||
sealed class ListenerType {
|
||||
sealed interface ListenerType {
|
||||
|
||||
sealed class Bookmark : ListenerType() {
|
||||
sealed class Bookmark : ListenerType {
|
||||
data class View(val item: BlockView.Media.Bookmark) : Bookmark()
|
||||
data class Placeholder(val target: String) : Bookmark()
|
||||
data class Error(val item: BlockView.Error.Bookmark) : Bookmark()
|
||||
}
|
||||
|
||||
sealed class File : ListenerType() {
|
||||
sealed class File : ListenerType {
|
||||
data class View(val target: String) : File()
|
||||
data class Placeholder(val target: String) : File()
|
||||
data class Upload(val target: String) : File()
|
||||
data class Error(val target: String) : File()
|
||||
}
|
||||
|
||||
sealed class Picture: ListenerType() {
|
||||
sealed class Picture: ListenerType {
|
||||
data class View(val target: String) : Picture()
|
||||
data class Placeholder(val target: String) : Picture()
|
||||
data class Upload(val target: String) : Picture()
|
||||
data class Error(val target: String) : Picture()
|
||||
}
|
||||
|
||||
sealed class Video : ListenerType() {
|
||||
sealed class Video : ListenerType {
|
||||
data class View(val target: String) : Video()
|
||||
data class Placeholder(val target: String) : Video()
|
||||
data class Upload(val target: String) : Video()
|
||||
data class Error(val target: String) : Video()
|
||||
}
|
||||
|
||||
sealed class Code : ListenerType() {
|
||||
sealed class Code : ListenerType {
|
||||
data class SelectLanguage(val target: String) : Code()
|
||||
}
|
||||
|
||||
data class LongClick(val target: String, val dimensions: BlockDimensions = BlockDimensions()) : ListenerType()
|
||||
sealed interface Callout : ListenerType {
|
||||
data class Icon(val blockId: String): Callout
|
||||
}
|
||||
|
||||
data class EditableBlock(val target: String) : ListenerType()
|
||||
data class LongClick(val target: String, val dimensions: BlockDimensions = BlockDimensions()) : ListenerType
|
||||
|
||||
object TitleBlock : ListenerType()
|
||||
object ProfileImageIcon : ListenerType()
|
||||
data class EditableBlock(val target: String) : ListenerType
|
||||
|
||||
data class LinkToObject(val target: String) : ListenerType()
|
||||
data class LinkToObjectArchived(val target: String) : ListenerType()
|
||||
data class LinkToObjectDeleted(val target: String) : ListenerType()
|
||||
object TitleBlock : ListenerType
|
||||
object ProfileImageIcon : ListenerType
|
||||
|
||||
data class Mention(val target: String) : ListenerType()
|
||||
data class LinkToObject(val target: String) : ListenerType
|
||||
data class LinkToObjectArchived(val target: String) : ListenerType
|
||||
data class LinkToObjectDeleted(val target: String) : ListenerType
|
||||
|
||||
data class DividerClick(val target: String) : ListenerType()
|
||||
data class Mention(val target: String) : ListenerType
|
||||
|
||||
data class Latex(val id: Id) : ListenerType()
|
||||
data class DividerClick(val target: String) : ListenerType
|
||||
|
||||
sealed class Relation : ListenerType() {
|
||||
data class Latex(val id: Id) : ListenerType
|
||||
|
||||
sealed class Relation : ListenerType {
|
||||
data class Placeholder(val target: Id) : Relation()
|
||||
data class Related(val value: BlockView.Relation) : Relation()
|
||||
data class ObjectType(val type: String) : Relation()
|
||||
|
@ -63,5 +67,5 @@ sealed class ListenerType {
|
|||
data class Featured(val relation: DocumentRelationView) : Relation()
|
||||
}
|
||||
|
||||
data class TableOfContentsItem(val target: Id, val item: Id) : ListenerType()
|
||||
data class TableOfContentsItem(val target: Id, val item: Id) : ListenerType
|
||||
}
|
|
@ -1,247 +0,0 @@
|
|||
package com.anytypeio.anytype.presentation.editor.picker
|
||||
|
||||
import androidx.lifecycle.viewModelScope
|
||||
import com.anytypeio.anytype.core_models.Payload
|
||||
import com.anytypeio.anytype.core_utils.ui.ViewStateViewModel
|
||||
import com.anytypeio.anytype.domain.icon.SetDocumentEmojiIcon
|
||||
import com.anytypeio.anytype.domain.icon.SetDocumentImageIcon
|
||||
import com.anytypeio.anytype.emojifier.data.Emoji
|
||||
import com.anytypeio.anytype.presentation.common.StateReducer
|
||||
import com.anytypeio.anytype.presentation.editor.editor.DetailModificationManager
|
||||
import com.anytypeio.anytype.presentation.editor.picker.DocumentIconActionMenuViewModel.Contract.*
|
||||
import com.anytypeio.anytype.presentation.editor.picker.DocumentIconActionMenuViewModel.ViewState
|
||||
import com.anytypeio.anytype.presentation.util.Dispatcher
|
||||
import kotlinx.coroutines.channels.Channel
|
||||
import kotlinx.coroutines.channels.ConflatedBroadcastChannel
|
||||
import kotlinx.coroutines.flow.*
|
||||
import kotlinx.coroutines.launch
|
||||
|
||||
@Deprecated("To be deleted")
|
||||
class DocumentIconActionMenuViewModel(
|
||||
private val setEmojiIcon: SetDocumentEmojiIcon,
|
||||
private val setImageIcon: SetDocumentImageIcon,
|
||||
private val dispatcher: Dispatcher<Payload>,
|
||||
private val details: DetailModificationManager
|
||||
) : ViewStateViewModel<ViewState>(), StateReducer<State, Event> {
|
||||
|
||||
private val events = ConflatedBroadcastChannel<Event>()
|
||||
private val actions = Channel<Action>()
|
||||
private val flow: Flow<State> = events.asFlow().scan(State.init(), function)
|
||||
|
||||
override val function: suspend (State, Event) -> State
|
||||
get() = { state, event -> reduce(state, event) }
|
||||
|
||||
init {
|
||||
flow
|
||||
.map { state ->
|
||||
when {
|
||||
state.error != null -> ViewState.Error(state.error)
|
||||
state.isCompleted -> ViewState.Exit
|
||||
state.isUploading -> ViewState.Uploading
|
||||
else -> ViewState.Idle
|
||||
}
|
||||
}
|
||||
.onEach { stateData.postValue(it) }
|
||||
.launchIn(viewModelScope)
|
||||
|
||||
actions
|
||||
.consumeAsFlow()
|
||||
.onEach { action ->
|
||||
when (action) {
|
||||
is Action.SetEmojiIcon -> setEmojiIcon(
|
||||
params = SetDocumentEmojiIcon.Params(
|
||||
target = action.target,
|
||||
emoji = action.unicode,
|
||||
context = action.context
|
||||
)
|
||||
).proceed(
|
||||
success = {
|
||||
dispatcher.send(it)
|
||||
details.setEmojiIcon(target = action.target, unicode = action.unicode)
|
||||
events.send(Event.OnCompleted)
|
||||
},
|
||||
failure = { events.send(Event.Failure(it)) }
|
||||
)
|
||||
is Action.ClearEmoji -> setEmojiIcon(
|
||||
params = SetDocumentEmojiIcon.Params(
|
||||
target = action.target,
|
||||
emoji = "",
|
||||
context = action.context
|
||||
)
|
||||
).proceed(
|
||||
success = { payload ->
|
||||
dispatcher.send(payload)
|
||||
details.removeIcon(action.target)
|
||||
events.send(Event.OnCompleted)
|
||||
},
|
||||
failure = { events.send(Event.Failure(it)) }
|
||||
)
|
||||
is Action.SetImageIcon -> setImageIcon(
|
||||
SetDocumentImageIcon.Params(
|
||||
context = action.context,
|
||||
path = action.path
|
||||
)
|
||||
).proceed(
|
||||
failure = { events.send(Event.Failure(it)) },
|
||||
success = { (payload, hash) ->
|
||||
dispatcher.send(payload)
|
||||
details.setImageIcon(target = action.context, hash = hash)
|
||||
events.send(Event.OnCompleted)
|
||||
}
|
||||
)
|
||||
is Action.PickRandomEmoji -> {
|
||||
val random = Emoji.DATA.random().random()
|
||||
events.send(
|
||||
Event.OnRandomEmojiSelected(
|
||||
target = action.target,
|
||||
context = action.context,
|
||||
unicode = random
|
||||
)
|
||||
)
|
||||
}
|
||||
}
|
||||
}
|
||||
.launchIn(viewModelScope)
|
||||
}
|
||||
|
||||
fun onEvent(event: Event) {
|
||||
viewModelScope.launch { events.send(event) }
|
||||
}
|
||||
|
||||
sealed class ViewState {
|
||||
object Loading : ViewState()
|
||||
object Uploading : ViewState()
|
||||
object Exit : ViewState()
|
||||
object Idle : ViewState()
|
||||
data class Error(val message: String) : ViewState()
|
||||
}
|
||||
|
||||
sealed class Contract {
|
||||
|
||||
sealed class Action {
|
||||
|
||||
class PickRandomEmoji(
|
||||
val context: String,
|
||||
val target: String
|
||||
) : Action()
|
||||
|
||||
class ClearEmoji(
|
||||
val target: String,
|
||||
val context: String
|
||||
) : Action()
|
||||
|
||||
class SetEmojiIcon(
|
||||
val unicode: String,
|
||||
val target: String,
|
||||
val context: String
|
||||
) : Action()
|
||||
|
||||
class SetImageIcon(
|
||||
val context: String,
|
||||
val path: String
|
||||
) : Action()
|
||||
}
|
||||
|
||||
data class State(
|
||||
val isLoading: Boolean,
|
||||
val isUploading: Boolean = false,
|
||||
val isCompleted: Boolean = false,
|
||||
val error: String? = null
|
||||
) : Contract() {
|
||||
companion object {
|
||||
fun init() = State(isLoading = false)
|
||||
}
|
||||
}
|
||||
|
||||
sealed class Event : Contract() {
|
||||
|
||||
class OnImagePickedFromGallery(
|
||||
val context: String,
|
||||
val path: String
|
||||
) : Event()
|
||||
|
||||
class OnSetRandomEmojiClicked(
|
||||
val target: String,
|
||||
val context: String
|
||||
) : Event()
|
||||
|
||||
class OnRandomEmojiSelected(
|
||||
val unicode: String,
|
||||
val context: String,
|
||||
val target: String
|
||||
) : Event()
|
||||
|
||||
class OnRemoveEmojiSelected(
|
||||
val context: String,
|
||||
val target: String
|
||||
) : Event()
|
||||
|
||||
object OnCompleted : Event()
|
||||
|
||||
class Failure(val error: Throwable) : Event()
|
||||
}
|
||||
}
|
||||
|
||||
override suspend fun reduce(state: State, event: Event): State {
|
||||
return when (event) {
|
||||
is Event.OnRandomEmojiSelected -> state.copy(
|
||||
isLoading = true
|
||||
).also {
|
||||
actions.send(
|
||||
Action.SetEmojiIcon(
|
||||
target = event.target,
|
||||
context = event.context,
|
||||
unicode = event.unicode
|
||||
)
|
||||
)
|
||||
}
|
||||
is Event.OnSetRandomEmojiClicked -> {
|
||||
state.copy(
|
||||
isLoading = true
|
||||
).also {
|
||||
actions.send(
|
||||
Action.PickRandomEmoji(
|
||||
target = event.target,
|
||||
context = event.context
|
||||
)
|
||||
)
|
||||
}
|
||||
}
|
||||
is Event.OnRemoveEmojiSelected -> {
|
||||
state.copy(
|
||||
isLoading = true
|
||||
).also {
|
||||
actions.send(
|
||||
Action.ClearEmoji(
|
||||
context = event.context,
|
||||
target = event.target
|
||||
)
|
||||
)
|
||||
}
|
||||
}
|
||||
is Event.OnImagePickedFromGallery -> {
|
||||
state.copy(
|
||||
isUploading = true,
|
||||
isLoading = false,
|
||||
).also {
|
||||
actions.send(
|
||||
Action.SetImageIcon(
|
||||
context = event.context,
|
||||
path = event.path
|
||||
)
|
||||
)
|
||||
}
|
||||
}
|
||||
is Event.OnCompleted -> state.copy(
|
||||
isLoading = false,
|
||||
isCompleted = true,
|
||||
error = null
|
||||
)
|
||||
is Event.Failure -> state.copy(
|
||||
isLoading = false,
|
||||
isCompleted = false,
|
||||
error = event.error.toString()
|
||||
)
|
||||
}
|
||||
}
|
||||
}
|
|
@ -1,25 +0,0 @@
|
|||
package com.anytypeio.anytype.presentation.editor.picker
|
||||
|
||||
import androidx.lifecycle.ViewModel
|
||||
import androidx.lifecycle.ViewModelProvider
|
||||
import com.anytypeio.anytype.core_models.Payload
|
||||
import com.anytypeio.anytype.domain.icon.SetDocumentEmojiIcon
|
||||
import com.anytypeio.anytype.domain.icon.SetDocumentImageIcon
|
||||
import com.anytypeio.anytype.presentation.editor.editor.DetailModificationManager
|
||||
import com.anytypeio.anytype.presentation.util.Dispatcher
|
||||
|
||||
class DocumentIconActionMenuViewModelFactory(
|
||||
private val setEmojiIcon: SetDocumentEmojiIcon,
|
||||
private val setImageIcon: SetDocumentImageIcon,
|
||||
private val dispatcher: Dispatcher<Payload>,
|
||||
private val details: DetailModificationManager
|
||||
) : ViewModelProvider.Factory {
|
||||
|
||||
@Suppress("UNCHECKED_CAST")
|
||||
override fun <T : ViewModel> create(modelClass: Class<T>): T = DocumentIconActionMenuViewModel(
|
||||
setEmojiIcon = setEmojiIcon,
|
||||
setImageIcon = setImageIcon,
|
||||
dispatcher = dispatcher,
|
||||
details = details
|
||||
) as T
|
||||
}
|
|
@ -5,11 +5,10 @@ import androidx.lifecycle.viewModelScope
|
|||
import com.anytypeio.anytype.analytics.base.Analytics
|
||||
import com.anytypeio.anytype.analytics.base.EventsDictionary
|
||||
import com.anytypeio.anytype.analytics.base.sendEvent
|
||||
import com.anytypeio.anytype.core_models.Id
|
||||
import com.anytypeio.anytype.core_models.Payload
|
||||
import com.anytypeio.anytype.domain.icon.RemoveDocumentIcon
|
||||
import com.anytypeio.anytype.domain.icon.SetDocumentEmojiIcon
|
||||
import com.anytypeio.anytype.domain.icon.SetDocumentImageIcon
|
||||
import com.anytypeio.anytype.domain.icon.RemoveIcon
|
||||
import com.anytypeio.anytype.domain.icon.SetEmojiIcon
|
||||
import com.anytypeio.anytype.domain.icon.SetImageIcon
|
||||
import com.anytypeio.anytype.emojifier.data.Emoji
|
||||
import com.anytypeio.anytype.emojifier.data.EmojiProvider
|
||||
import com.anytypeio.anytype.emojifier.suggest.EmojiSuggester
|
||||
|
@ -17,15 +16,21 @@ import com.anytypeio.anytype.emojifier.suggest.model.EmojiSuggest
|
|||
import com.anytypeio.anytype.presentation.editor.editor.Proxy
|
||||
import com.anytypeio.anytype.presentation.util.Dispatcher
|
||||
import kotlinx.coroutines.Dispatchers
|
||||
import kotlinx.coroutines.flow.*
|
||||
import kotlinx.coroutines.flow.MutableStateFlow
|
||||
import kotlinx.coroutines.flow.StateFlow
|
||||
import kotlinx.coroutines.flow.debounce
|
||||
import kotlinx.coroutines.flow.distinctUntilChanged
|
||||
import kotlinx.coroutines.flow.flowOn
|
||||
import kotlinx.coroutines.flow.mapLatest
|
||||
import kotlinx.coroutines.flow.onEach
|
||||
import kotlinx.coroutines.launch
|
||||
import kotlinx.coroutines.withContext
|
||||
import timber.log.Timber
|
||||
|
||||
abstract class ObjectIconPickerBaseViewModel(
|
||||
private val setEmojiIcon: SetDocumentEmojiIcon,
|
||||
private val setImageIcon: SetDocumentImageIcon,
|
||||
private val removeDocumentIcon: RemoveDocumentIcon,
|
||||
class IconPickerViewModel<Iconable>(
|
||||
private val setEmojiIcon: SetEmojiIcon<Iconable>,
|
||||
private val setImageIcon: SetImageIcon<Iconable>,
|
||||
private val removeDocumentIcon: RemoveIcon<Iconable>,
|
||||
private val provider: EmojiProvider,
|
||||
private val suggester: EmojiSuggester,
|
||||
private val dispatcher: Dispatcher<Payload>,
|
||||
|
@ -126,13 +131,22 @@ abstract class ObjectIconPickerBaseViewModel(
|
|||
|
||||
fun state(): StateFlow<ViewState> = state
|
||||
|
||||
fun onEmojiClicked(unicode: String, target: Id, context: Id) {
|
||||
fun onEmojiClicked(unicode: String, iconable: Iconable) {
|
||||
setEmoji(iconable, unicode)
|
||||
}
|
||||
|
||||
fun onRandomEmoji(iconable: Iconable) {
|
||||
setEmoji(iconable, provider.emojis.random().random())
|
||||
}
|
||||
|
||||
private fun setEmoji(
|
||||
iconable: Iconable, emojiUnicode: String
|
||||
) {
|
||||
viewModelScope.launch {
|
||||
setEmojiIcon(
|
||||
params = SetDocumentEmojiIcon.Params(
|
||||
emoji = unicode,
|
||||
target = target,
|
||||
context = context
|
||||
params = SetEmojiIcon.Params(
|
||||
emoji = emojiUnicode,
|
||||
target = iconable
|
||||
)
|
||||
).process(
|
||||
failure = { Timber.e(it, "Error while setting emoji") },
|
||||
|
@ -148,28 +162,10 @@ abstract class ObjectIconPickerBaseViewModel(
|
|||
}
|
||||
}
|
||||
|
||||
fun onRandomEmoji(ctx: Id, target: Id) {
|
||||
fun onRemoveClicked(iconable: Iconable) {
|
||||
viewModelScope.launch {
|
||||
setEmojiIcon(
|
||||
params = SetDocumentEmojiIcon.Params(
|
||||
emoji = provider.emojis.random().random(),
|
||||
target = target,
|
||||
context = ctx
|
||||
)
|
||||
).process(
|
||||
failure = { Timber.e(it, "Error while setting emoji") },
|
||||
success = { payload ->
|
||||
if (payload.events.isNotEmpty()) dispatcher.send(payload)
|
||||
state.value = ViewState.Exit
|
||||
}
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
fun onRemoveClicked(ctx: Id) {
|
||||
viewModelScope.launch {
|
||||
removeDocumentIcon(RemoveDocumentIcon.Params(ctx = ctx)).process(
|
||||
failure = { Timber.e(it, "Error while setting emoji") },
|
||||
removeDocumentIcon(iconable).process(
|
||||
failure = { Timber.e(it, "Error while removing icon") },
|
||||
success = { payload ->
|
||||
sendEvent(
|
||||
analytics = analytics,
|
||||
|
@ -182,20 +178,22 @@ abstract class ObjectIconPickerBaseViewModel(
|
|||
}
|
||||
}
|
||||
|
||||
fun onPickedFromDevice(ctx: Id, path: String) {
|
||||
fun onPickedFromDevice(iconable: Iconable, path: String) {
|
||||
viewModelScope.launch {
|
||||
state.value = ViewState.Loading
|
||||
setImageIcon(
|
||||
SetDocumentImageIcon.Params(
|
||||
context = ctx,
|
||||
SetImageIcon.Params(
|
||||
target = iconable,
|
||||
path = path
|
||||
)
|
||||
).process(
|
||||
failure = {
|
||||
Timber.e("Error while setting image icon").also { state.value = ViewState.Init }
|
||||
Timber.e("Error while setting image icon")
|
||||
state.value = ViewState.Init
|
||||
},
|
||||
success = { (payload, _) ->
|
||||
dispatcher.send(payload).also { state.value = ViewState.Exit }
|
||||
dispatcher.send(payload)
|
||||
state.value = ViewState.Exit
|
||||
}
|
||||
)
|
||||
}
|
||||
|
@ -215,40 +213,4 @@ abstract class ObjectIconPickerBaseViewModel(
|
|||
companion object {
|
||||
const val DEBOUNCE_DURATION = 300L
|
||||
}
|
||||
}
|
||||
|
||||
class ObjectIconPickerViewModel(
|
||||
setEmojiIcon: SetDocumentEmojiIcon,
|
||||
setImageIcon: SetDocumentImageIcon,
|
||||
removeDocumentIcon: RemoveDocumentIcon,
|
||||
provider: EmojiProvider,
|
||||
suggester: EmojiSuggester,
|
||||
dispatcher: Dispatcher<Payload>,
|
||||
analytics: Analytics
|
||||
) : ObjectIconPickerBaseViewModel(
|
||||
setEmojiIcon = setEmojiIcon,
|
||||
setImageIcon = setImageIcon,
|
||||
removeDocumentIcon = removeDocumentIcon,
|
||||
provider = provider,
|
||||
suggester = suggester,
|
||||
dispatcher = dispatcher,
|
||||
analytics = analytics
|
||||
)
|
||||
|
||||
class ObjectSetIconPickerViewModel(
|
||||
setEmojiIcon: SetDocumentEmojiIcon,
|
||||
setImageIcon: SetDocumentImageIcon,
|
||||
removeDocumentIcon: RemoveDocumentIcon,
|
||||
provider: EmojiProvider,
|
||||
suggester: EmojiSuggester,
|
||||
dispatcher: Dispatcher<Payload>,
|
||||
analytics: Analytics
|
||||
) : ObjectIconPickerBaseViewModel(
|
||||
setEmojiIcon = setEmojiIcon,
|
||||
setImageIcon = setImageIcon,
|
||||
removeDocumentIcon = removeDocumentIcon,
|
||||
provider = provider,
|
||||
suggester = suggester,
|
||||
dispatcher = dispatcher,
|
||||
analytics = analytics
|
||||
)
|
||||
}
|
|
@ -23,7 +23,7 @@ class ObjectIconPickerViewModelFactory(
|
|||
|
||||
@Suppress("UNCHECKED_CAST")
|
||||
override fun <T : ViewModel> create(modelClass: Class<T>): T {
|
||||
return ObjectIconPickerViewModel(
|
||||
return IconPickerViewModel(
|
||||
setEmojiIcon = setEmojiIcon,
|
||||
setImageIcon = setImageIcon,
|
||||
removeDocumentIcon = removeDocumentIcon,
|
||||
|
@ -47,7 +47,7 @@ class ObjectSetIconPickerViewModelFactory(
|
|||
|
||||
@Suppress("UNCHECKED_CAST")
|
||||
override fun <T : ViewModel> create(modelClass: Class<T>): T {
|
||||
return ObjectSetIconPickerViewModel(
|
||||
return IconPickerViewModel(
|
||||
setEmojiIcon = setEmojiIcon,
|
||||
setImageIcon = setImageIcon,
|
||||
removeDocumentIcon = removeDocumentIcon,
|
||||
|
|
|
@ -0,0 +1,36 @@
|
|||
package com.anytypeio.anytype.presentation.editor.picker
|
||||
|
||||
import androidx.lifecycle.ViewModel
|
||||
import androidx.lifecycle.ViewModelProvider
|
||||
import com.anytypeio.anytype.analytics.base.Analytics
|
||||
import com.anytypeio.anytype.core_models.Payload
|
||||
import com.anytypeio.anytype.domain.icon.RemoveTextBlockIcon
|
||||
import com.anytypeio.anytype.domain.icon.SetTextBlockEmoji
|
||||
import com.anytypeio.anytype.domain.icon.SetTextBlockImage
|
||||
import com.anytypeio.anytype.emojifier.data.EmojiProvider
|
||||
import com.anytypeio.anytype.emojifier.suggest.EmojiSuggester
|
||||
import com.anytypeio.anytype.presentation.util.Dispatcher
|
||||
|
||||
class TextBlockIconPickerViewModelFactory(
|
||||
private val setEmojiIcon: SetTextBlockEmoji,
|
||||
private val setImageIcon: SetTextBlockImage,
|
||||
private val removeDocumentIcon: RemoveTextBlockIcon,
|
||||
private val emojiSuggester: EmojiSuggester,
|
||||
private val emojiProvider: EmojiProvider,
|
||||
private val dispatcher: Dispatcher<Payload>,
|
||||
private val analytics: Analytics
|
||||
) : ViewModelProvider.Factory {
|
||||
|
||||
@Suppress("UNCHECKED_CAST")
|
||||
override fun <T : ViewModel> create(modelClass: Class<T>): T {
|
||||
return IconPickerViewModel(
|
||||
setEmojiIcon = setEmojiIcon,
|
||||
setImageIcon = setImageIcon,
|
||||
removeDocumentIcon = removeDocumentIcon,
|
||||
suggester = emojiSuggester,
|
||||
provider = emojiProvider,
|
||||
dispatcher = dispatcher,
|
||||
analytics = analytics
|
||||
) as T
|
||||
}
|
||||
}
|
Loading…
Add table
Add a link
Reference in a new issue