mirror of
https://github.com/anyproto/anytype-kotlin.git
synced 2025-06-08 05:47:05 +09:00
Middleware | Integrate 0.9.0 (#417)
This commit is contained in:
parent
045a02141d
commit
ad9b4905d1
76 changed files with 3281 additions and 1921 deletions
17
CHANGELOG.md
17
CHANGELOG.md
|
@ -1,5 +1,22 @@
|
|||
# Change log for Android @Anytype app.
|
||||
|
||||
## Version 0.0.31
|
||||
|
||||
### New features 🚀
|
||||
|
||||
|
||||
|
||||
### Fixes & tech 🚒
|
||||
|
||||
* Migrate from short name emojis to unicode when parsing document icons (#408)
|
||||
* Consuming event payload from middleware callaback responses (#408)
|
||||
* Hard-coded alpha invite code for internal use (#408)
|
||||
* `PageViewModel` refactoring (#408)
|
||||
|
||||
### Middleware ⚙️
|
||||
|
||||
* Updated middleware to `0.9.0` (#339)
|
||||
|
||||
## Version 0.0.30
|
||||
|
||||
### New features 🚀
|
||||
|
|
|
@ -94,7 +94,7 @@ class ComponentManager(private val main: MainComponent) {
|
|||
.build()
|
||||
}
|
||||
|
||||
val pageComponent = Component {
|
||||
val pageComponent = ComponentMap {
|
||||
main
|
||||
.pageComponentBuilder()
|
||||
.pageModule(PageModule())
|
||||
|
@ -141,4 +141,17 @@ class ComponentManager(private val main: MainComponent) {
|
|||
instance = null
|
||||
}
|
||||
}
|
||||
|
||||
class ComponentMap<T>(private val builder: () -> T) {
|
||||
|
||||
private val map = mutableMapOf<String, T>()
|
||||
|
||||
fun get(id: String) = map[id] ?: builder().also { map[id] = it }
|
||||
|
||||
fun new(id: String) = builder().also { map[id] = it }
|
||||
|
||||
fun release(id: String) {
|
||||
map.remove(id)
|
||||
}
|
||||
}
|
||||
}
|
|
@ -13,6 +13,7 @@ import com.agileburo.anytype.domain.event.interactor.InterceptEvents
|
|||
import com.agileburo.anytype.domain.image.ImageLoader
|
||||
import com.agileburo.anytype.domain.image.LoadImage
|
||||
import com.agileburo.anytype.domain.page.CreatePage
|
||||
import com.agileburo.anytype.presentation.desktop.HomeDashboardEventConverter
|
||||
import com.agileburo.anytype.presentation.desktop.HomeDashboardViewModelFactory
|
||||
import com.agileburo.anytype.ui.desktop.HomeDashboardFragment
|
||||
import dagger.Module
|
||||
|
@ -49,7 +50,8 @@ class HomeDashboardModule {
|
|||
closeDashboard: CloseDashboard,
|
||||
getConfig: GetConfig,
|
||||
dnd: DragAndDrop,
|
||||
interceptEvents: InterceptEvents
|
||||
interceptEvents: InterceptEvents,
|
||||
eventConverter: HomeDashboardEventConverter
|
||||
): HomeDashboardViewModelFactory = HomeDashboardViewModelFactory(
|
||||
getCurrentAccount = getCurrentAccount,
|
||||
loadImage = loadImage,
|
||||
|
@ -58,7 +60,8 @@ class HomeDashboardModule {
|
|||
closeDashboard = closeDashboard,
|
||||
getConfig = getConfig,
|
||||
dnd = dnd,
|
||||
interceptEvents = interceptEvents
|
||||
interceptEvents = interceptEvents,
|
||||
eventConverter = eventConverter
|
||||
)
|
||||
|
||||
@Provides
|
||||
|
@ -126,4 +129,10 @@ class HomeDashboardModule {
|
|||
context = Dispatchers.IO,
|
||||
channel = channel
|
||||
)
|
||||
|
||||
@Provides
|
||||
@PerScreen
|
||||
fun provideEventConverter(): HomeDashboardEventConverter {
|
||||
return HomeDashboardEventConverter.DefaultConverter()
|
||||
}
|
||||
}
|
|
@ -7,13 +7,15 @@ import com.agileburo.anytype.domain.block.interactor.*
|
|||
import com.agileburo.anytype.domain.block.repo.BlockRepository
|
||||
import com.agileburo.anytype.domain.download.DownloadFile
|
||||
import com.agileburo.anytype.domain.download.Downloader
|
||||
import com.agileburo.anytype.domain.emoji.Emojifier
|
||||
import com.agileburo.anytype.domain.event.interactor.EventChannel
|
||||
import com.agileburo.anytype.domain.event.interactor.InterceptEvents
|
||||
import com.agileburo.anytype.domain.misc.UrlBuilder
|
||||
import com.agileburo.anytype.domain.page.*
|
||||
import com.agileburo.anytype.presentation.page.DocumentExternalEventReducer
|
||||
import com.agileburo.anytype.presentation.page.Editor
|
||||
import com.agileburo.anytype.presentation.page.PageViewModelFactory
|
||||
import com.agileburo.anytype.presentation.page.editor.Interactor
|
||||
import com.agileburo.anytype.presentation.page.editor.Orchestrator
|
||||
import com.agileburo.anytype.presentation.page.render.DefaultBlockViewRenderer
|
||||
import com.agileburo.anytype.presentation.page.selection.SelectionStateHolder
|
||||
import com.agileburo.anytype.presentation.page.toggle.ToggleStateHolder
|
||||
|
@ -44,67 +46,31 @@ class PageModule {
|
|||
fun providePageViewModelFactory(
|
||||
openPage: OpenPage,
|
||||
closePage: ClosePage,
|
||||
undo: Undo,
|
||||
redo: Redo,
|
||||
updateText: UpdateText,
|
||||
createBlock: CreateBlock,
|
||||
interceptEvents: InterceptEvents,
|
||||
updateCheckbox: UpdateCheckbox,
|
||||
unlinkBlocks: UnlinkBlocks,
|
||||
updateLinkMarks: UpdateLinkMarks,
|
||||
removeLinkMark: RemoveLinkMark,
|
||||
duplicateBlock: DuplicateBlock,
|
||||
updateTextStyle: UpdateTextStyle,
|
||||
updateTextColor: UpdateTextColor,
|
||||
updateBackgroundColor: UpdateBackgroundColor,
|
||||
mergeBlocks: MergeBlocks,
|
||||
splitBlock: SplitBlock,
|
||||
createPage: CreatePage,
|
||||
createDocument: CreateDocument,
|
||||
uploadUrl: UploadUrl,
|
||||
documentExternalEventReducer: DocumentExternalEventReducer,
|
||||
urlBuilder: UrlBuilder,
|
||||
downloadFile: DownloadFile,
|
||||
renderer: DefaultBlockViewRenderer,
|
||||
counter: Counter,
|
||||
archiveDocument: ArchiveDocument,
|
||||
replaceBlock: ReplaceBlock,
|
||||
patternMatcher: DefaultPatternMatcher,
|
||||
updateTitle: UpdateTitle,
|
||||
selectionStateHolder: SelectionStateHolder,
|
||||
updateAlignment: UpdateBlockAlignment
|
||||
interactor: Orchestrator
|
||||
): PageViewModelFactory = PageViewModelFactory(
|
||||
openPage = openPage,
|
||||
closePage = closePage,
|
||||
createPage = createPage,
|
||||
createDocument = createDocument,
|
||||
updateText = updateText,
|
||||
createBlock = createBlock,
|
||||
interceptEvents = interceptEvents,
|
||||
updateCheckbox = updateCheckbox,
|
||||
unlinkBlocks = unlinkBlocks,
|
||||
duplicateBlock = duplicateBlock,
|
||||
updateTextStyle = updateTextStyle,
|
||||
updateTextColor = updateTextColor,
|
||||
updateBackgroundColor = updateBackgroundColor,
|
||||
updateLinkMarks = updateLinkMarks,
|
||||
removeLinkMark = removeLinkMark,
|
||||
mergeBlocks = mergeBlocks,
|
||||
uploadUrl = uploadUrl,
|
||||
splitBlock = splitBlock,
|
||||
documentEventReducer = documentExternalEventReducer,
|
||||
urlBuilder = urlBuilder,
|
||||
downloadFile = downloadFile,
|
||||
renderer = renderer,
|
||||
counter = counter,
|
||||
undo = undo,
|
||||
redo = redo,
|
||||
archiveDocument = archiveDocument,
|
||||
replaceBlock = replaceBlock,
|
||||
patternMatcher = patternMatcher,
|
||||
updateTitle = updateTitle,
|
||||
selectionStateHolder = selectionStateHolder,
|
||||
updateAlignment = updateAlignment
|
||||
interactor = interactor
|
||||
)
|
||||
|
||||
@Provides
|
||||
|
@ -220,14 +186,6 @@ class PageModule {
|
|||
repo = repo
|
||||
)
|
||||
|
||||
@Provides
|
||||
@PerScreen
|
||||
fun provideUpdateAlignmentUseCase(
|
||||
repo: BlockRepository
|
||||
): UpdateBlockAlignment = UpdateBlockAlignment(
|
||||
repo = repo
|
||||
)
|
||||
|
||||
@Provides
|
||||
@PerScreen
|
||||
fun provideUpdateBackgroundColorUseCase(
|
||||
|
@ -256,13 +214,13 @@ class PageModule {
|
|||
@Provides
|
||||
@PerScreen
|
||||
fun provideDefaultBlockViewRenderer(
|
||||
emojifier: Emojifier,
|
||||
urlBuilder: UrlBuilder,
|
||||
toggleStateHolder: ToggleStateHolder
|
||||
toggleStateHolder: ToggleStateHolder,
|
||||
counter: Counter
|
||||
): DefaultBlockViewRenderer = DefaultBlockViewRenderer(
|
||||
urlBuilder = urlBuilder,
|
||||
emojifier = emojifier,
|
||||
toggleStateHolder = toggleStateHolder
|
||||
toggleStateHolder = toggleStateHolder,
|
||||
counter = counter
|
||||
)
|
||||
|
||||
@Provides
|
||||
|
@ -333,4 +291,86 @@ class PageModule {
|
|||
@Provides
|
||||
@PerScreen
|
||||
fun provideSelectionStateHolder(): SelectionStateHolder = SelectionStateHolder.Default()
|
||||
|
||||
@Provides
|
||||
@PerScreen
|
||||
fun provideMemory(
|
||||
selectionStateHolder: SelectionStateHolder
|
||||
): Editor.Memory = Editor.Memory(
|
||||
selections = selectionStateHolder
|
||||
)
|
||||
|
||||
@Provides
|
||||
@PerScreen
|
||||
fun provideInteractor(
|
||||
storage: Editor.Storage,
|
||||
proxer: Editor.Proxer,
|
||||
memory: Editor.Memory,
|
||||
createBlock: CreateBlock,
|
||||
replaceBlock: ReplaceBlock,
|
||||
duplicateBlock: DuplicateBlock,
|
||||
updateTextColor: UpdateTextColor,
|
||||
updateBackgroundColor: UpdateBackgroundColor,
|
||||
splitBlock: SplitBlock,
|
||||
mergeBlocks: MergeBlocks,
|
||||
unlinkBlocks: UnlinkBlocks,
|
||||
updateTextStyle: UpdateTextStyle,
|
||||
updateCheckbox: UpdateCheckbox,
|
||||
downloadFile: DownloadFile,
|
||||
updateTitle: UpdateTitle,
|
||||
updateText: UpdateText,
|
||||
updateAlignment: UpdateAlignment,
|
||||
textInteractor: Interactor.TextInteractor,
|
||||
undo: Undo,
|
||||
redo: Redo
|
||||
): Orchestrator = Orchestrator(
|
||||
stores = storage,
|
||||
createBlock = createBlock,
|
||||
replaceBlock = replaceBlock,
|
||||
proxies = proxer,
|
||||
duplicateBlock = duplicateBlock,
|
||||
updateBackgroundColor = updateBackgroundColor,
|
||||
updateTextColor = updateTextColor,
|
||||
splitBlock = splitBlock,
|
||||
mergeBlocks = mergeBlocks,
|
||||
unlinkBlocks = unlinkBlocks,
|
||||
undo = undo,
|
||||
redo = redo,
|
||||
updateTextStyle = updateTextStyle,
|
||||
updateCheckbox = updateCheckbox,
|
||||
memory = memory,
|
||||
downloadFile = downloadFile,
|
||||
updateTitle = updateTitle,
|
||||
textInteractor = textInteractor,
|
||||
updateText = updateText,
|
||||
updateAlignment = updateAlignment
|
||||
)
|
||||
|
||||
@Provides
|
||||
@PerScreen
|
||||
fun provideProxer(): Editor.Proxer = Editor.Proxer()
|
||||
|
||||
@Provides
|
||||
@PerScreen
|
||||
fun provideStorage(): Editor.Storage = Editor.Storage()
|
||||
|
||||
@Provides
|
||||
@PerScreen
|
||||
fun provideTextInteractor(
|
||||
proxer: Editor.Proxer,
|
||||
storage: Editor.Storage,
|
||||
matcher: DefaultPatternMatcher
|
||||
): Interactor.TextInteractor = Interactor.TextInteractor(
|
||||
proxies = proxer,
|
||||
stores = storage,
|
||||
matcher = matcher
|
||||
)
|
||||
|
||||
@Provides
|
||||
@PerScreen
|
||||
fun provideUpdateAlignmentUseCase(
|
||||
repo: BlockRepository
|
||||
): UpdateAlignment = UpdateAlignment(
|
||||
repo = repo
|
||||
)
|
||||
}
|
|
@ -108,7 +108,7 @@ class HomeDashboardFragment : ViewStateFragment<State>(R.layout.fragment_desktop
|
|||
state.dashboard?.let { dashboard ->
|
||||
lifecycleScope.launch {
|
||||
val result = withContext(Dispatchers.IO) {
|
||||
dashboard.toView(emojifier = emojifier)
|
||||
dashboard.toView()
|
||||
}
|
||||
dashboardAdapter.update(result)
|
||||
}
|
||||
|
|
|
@ -45,6 +45,8 @@ import com.agileburo.anytype.domain.ext.getSubstring
|
|||
import com.agileburo.anytype.ext.extractMarks
|
||||
import com.agileburo.anytype.presentation.page.PageViewModel
|
||||
import com.agileburo.anytype.presentation.page.PageViewModelFactory
|
||||
import com.agileburo.anytype.presentation.page.editor.Command
|
||||
import com.agileburo.anytype.presentation.page.editor.ViewState
|
||||
import com.agileburo.anytype.ui.base.NavigationFragment
|
||||
import com.agileburo.anytype.ui.page.modals.*
|
||||
import com.agileburo.anytype.ui.page.modals.actions.BlockActionToolbarFactory
|
||||
|
@ -472,42 +474,42 @@ open class PageFragment :
|
|||
}
|
||||
}
|
||||
|
||||
private fun execute(event: EventWrapper<PageViewModel.Command>) {
|
||||
private fun execute(event: EventWrapper<Command>) {
|
||||
event.getContentIfNotHandled()?.let { command ->
|
||||
when (command) {
|
||||
is PageViewModel.Command.OpenPagePicker -> {
|
||||
is Command.OpenPagePicker -> {
|
||||
PageIconPickerFragment.newInstance(
|
||||
context = requireArguments().getString(ID_KEY, ID_EMPTY_VALUE),
|
||||
target = command.target
|
||||
).show(childFragmentManager, null)
|
||||
}
|
||||
is PageViewModel.Command.OpenAddBlockPanel -> {
|
||||
is Command.OpenAddBlockPanel -> {
|
||||
AddBlockFragment.newInstance().show(childFragmentManager, null)
|
||||
}
|
||||
is PageViewModel.Command.OpenTurnIntoPanel -> {
|
||||
is Command.OpenTurnIntoPanel -> {
|
||||
TurnIntoFragment.single(
|
||||
target = command.target
|
||||
).show(childFragmentManager, null)
|
||||
}
|
||||
is PageViewModel.Command.OpenMultiSelectTurnIntoPanel -> {
|
||||
is Command.OpenMultiSelectTurnIntoPanel -> {
|
||||
TurnIntoFragment.multiple().show(childFragmentManager, null)
|
||||
}
|
||||
is PageViewModel.Command.OpenBookmarkSetter -> {
|
||||
is Command.OpenBookmarkSetter -> {
|
||||
CreateBookmarkFragment.newInstance(
|
||||
context = command.context,
|
||||
target = command.target
|
||||
).show(childFragmentManager, null)
|
||||
}
|
||||
is PageViewModel.Command.OpenGallery -> {
|
||||
is Command.OpenGallery -> {
|
||||
openGalleryWithPermissionCheck(command.mediaType)
|
||||
}
|
||||
is PageViewModel.Command.RequestDownloadPermission -> {
|
||||
is Command.RequestDownloadPermission -> {
|
||||
startDownloadWithPermissionCheck(command.id)
|
||||
}
|
||||
is PageViewModel.Command.PopBackStack -> {
|
||||
is Command.PopBackStack -> {
|
||||
childFragmentManager.popBackStack()
|
||||
}
|
||||
is PageViewModel.Command.OpenActionBar -> {
|
||||
is Command.OpenActionBar -> {
|
||||
hideKeyboard()
|
||||
childFragmentManager.beginTransaction()
|
||||
.setCustomAnimations(R.anim.action_bar_enter, R.anim.action_bar_exit)
|
||||
|
@ -515,10 +517,10 @@ open class PageFragment :
|
|||
.addToBackStack(null)
|
||||
.commit()
|
||||
}
|
||||
is PageViewModel.Command.CloseKeyboard -> {
|
||||
is Command.CloseKeyboard -> {
|
||||
hideSoftInput()
|
||||
}
|
||||
is PageViewModel.Command.Browse -> {
|
||||
is Command.Browse -> {
|
||||
try {
|
||||
Intent(Intent.ACTION_VIEW).apply {
|
||||
data = Uri.parse(command.url)
|
||||
|
@ -533,13 +535,13 @@ open class PageFragment :
|
|||
}
|
||||
}
|
||||
|
||||
private fun render(state: PageViewModel.ViewState) {
|
||||
private fun render(state: ViewState) {
|
||||
when (state) {
|
||||
is PageViewModel.ViewState.Success -> {
|
||||
is ViewState.Success -> {
|
||||
pageAdapter.updateWithDiffUtil(state.blocks)
|
||||
resetDocumentTitle(state)
|
||||
}
|
||||
is PageViewModel.ViewState.OpenLinkScreen -> {
|
||||
is ViewState.OpenLinkScreen -> {
|
||||
SetLinkFragment.newInstance(
|
||||
blockId = state.block.id,
|
||||
initUrl = state.block.getFirstLinkMarkupParam(state.range),
|
||||
|
@ -548,11 +550,11 @@ open class PageFragment :
|
|||
rangeStart = state.range.first
|
||||
).show(childFragmentManager, null)
|
||||
}
|
||||
is PageViewModel.ViewState.Error -> toast(state.message)
|
||||
is ViewState.Error -> toast(state.message)
|
||||
}
|
||||
}
|
||||
|
||||
private fun resetDocumentTitle(state: PageViewModel.ViewState.Success) {
|
||||
private fun resetDocumentTitle(state: ViewState.Success) {
|
||||
state.blocks.firstOrNull { view ->
|
||||
view is BlockView.Title
|
||||
}?.let { view ->
|
||||
|
@ -648,11 +650,11 @@ open class PageFragment :
|
|||
}
|
||||
|
||||
override fun injectDependencies() {
|
||||
componentManager().pageComponent.get().inject(this)
|
||||
componentManager().pageComponent.get(extractDocumentId()).inject(this)
|
||||
}
|
||||
|
||||
override fun releaseDependencies() {
|
||||
componentManager().pageComponent.release()
|
||||
componentManager().pageComponent.release(extractDocumentId())
|
||||
}
|
||||
|
||||
companion object {
|
||||
|
|
|
@ -21,8 +21,4 @@ abstract class BaseFragment(
|
|||
super.onDestroy()
|
||||
if (fragmentScope) releaseDependencies()
|
||||
}
|
||||
|
||||
companion object {
|
||||
const val CORE_COMPONENT_PROVIDER_ERROR = "Activity should implement core component provider"
|
||||
}
|
||||
}
|
|
@ -9,6 +9,7 @@ import com.agileburo.anytype.domain.block.model.Command
|
|||
import com.agileburo.anytype.domain.block.model.Position
|
||||
import com.agileburo.anytype.domain.config.Config
|
||||
import com.agileburo.anytype.domain.event.model.Event
|
||||
import com.agileburo.anytype.domain.event.model.Payload
|
||||
|
||||
fun AccountEntity.toDomain(): Account {
|
||||
return Account(
|
||||
|
@ -88,6 +89,7 @@ fun BlockEntity.Content.toDomain(): Block.Content = when (this) {
|
|||
is BlockEntity.Content.File -> toDomain()
|
||||
is BlockEntity.Content.Icon -> toDomain()
|
||||
is BlockEntity.Content.Bookmark -> toDomain()
|
||||
is BlockEntity.Content.Smart -> toDomain()
|
||||
}
|
||||
|
||||
fun BlockEntity.Content.File.toDomain(): Block.Content.File {
|
||||
|
@ -185,6 +187,11 @@ fun BlockEntity.Content.Image.toDomain(): Block.Content.Image {
|
|||
|
||||
fun BlockEntity.Content.Divider.toDomain() = Block.Content.Divider
|
||||
|
||||
|
||||
fun BlockEntity.Content.Smart.toDomain() = Block.Content.Smart(
|
||||
type = Block.Content.Smart.Type.valueOf(type.name)
|
||||
)
|
||||
|
||||
fun Block.Content.Image.toEntity(): BlockEntity.Content.Image {
|
||||
return BlockEntity.Content.Image(
|
||||
path = path
|
||||
|
@ -219,6 +226,7 @@ fun Block.Content.toEntity(): BlockEntity.Content = when (this) {
|
|||
is Block.Content.File -> toEntity()
|
||||
is Block.Content.Icon -> toEntity()
|
||||
is Block.Content.Bookmark -> toEntity()
|
||||
is Block.Content.Smart -> toEntity()
|
||||
}
|
||||
|
||||
fun Block.Content.File.toEntity(): BlockEntity.Content.File {
|
||||
|
@ -444,6 +452,11 @@ fun Position.toEntity(): PositionEntity {
|
|||
return PositionEntity.valueOf(name)
|
||||
}
|
||||
|
||||
fun PayloadEntity.toDomain(): Payload = Payload(
|
||||
context = context,
|
||||
events = events.map { it.toDomain() }
|
||||
)
|
||||
|
||||
fun EventEntity.toDomain(): Event {
|
||||
return when (this) {
|
||||
is EventEntity.Command.ShowBlock -> {
|
||||
|
|
|
@ -14,6 +14,12 @@ data class BlockEntity(
|
|||
|
||||
sealed class Content {
|
||||
|
||||
data class Smart(
|
||||
val type: Type
|
||||
) : Content() {
|
||||
enum class Type { HOME, PAGE, ARCHIVE, BREADCRUMBS, PROFILE }
|
||||
}
|
||||
|
||||
data class Text(
|
||||
val text: String,
|
||||
val style: Style,
|
||||
|
@ -47,7 +53,7 @@ data class BlockEntity(
|
|||
}
|
||||
|
||||
data class Layout(val type: Type) : Content() {
|
||||
enum class Type { ROW, COLUMN }
|
||||
enum class Type { ROW, COLUMN, DIV }
|
||||
}
|
||||
|
||||
data class Image(
|
||||
|
|
|
@ -0,0 +1,6 @@
|
|||
package com.agileburo.anytype.data.auth.model
|
||||
|
||||
data class PayloadEntity(
|
||||
val context: String,
|
||||
val events: List<EventEntity>
|
||||
)
|
|
@ -5,6 +5,7 @@ import com.agileburo.anytype.data.auth.mapper.toEntity
|
|||
import com.agileburo.anytype.domain.block.model.Command
|
||||
import com.agileburo.anytype.domain.block.repo.BlockRepository
|
||||
import com.agileburo.anytype.domain.common.Id
|
||||
import com.agileburo.anytype.domain.event.model.Payload
|
||||
|
||||
class BlockDataRepository(
|
||||
private val factory: BlockDataStoreFactory
|
||||
|
@ -12,24 +13,23 @@ class BlockDataRepository(
|
|||
|
||||
override suspend fun getConfig() = factory.remote.getConfig().toDomain()
|
||||
|
||||
override suspend fun openDashboard(contextId: String, id: String) {
|
||||
factory.remote.openDashboard(id = id, contextId = contextId)
|
||||
}
|
||||
override suspend fun openDashboard(
|
||||
contextId: String,
|
||||
id: String
|
||||
) = factory.remote.openDashboard(id = id, contextId = contextId).toDomain()
|
||||
|
||||
override suspend fun openPage(id: String): Payload = factory.remote.openPage(id).toDomain()
|
||||
|
||||
override suspend fun closeDashboard(id: String) {
|
||||
factory.remote.closeDashboard(id)
|
||||
}
|
||||
|
||||
override suspend fun updateAlignment(command: Command.UpdateAlignment) {
|
||||
factory.remote.updateAlignment(command.toEntity())
|
||||
}
|
||||
override suspend fun updateAlignment(
|
||||
command: Command.UpdateAlignment
|
||||
) : Payload = factory.remote.updateAlignment(command.toEntity()).toDomain()
|
||||
|
||||
override suspend fun createPage(parentId: String) = factory.remote.createPage(parentId)
|
||||
|
||||
override suspend fun openPage(id: String) {
|
||||
factory.remote.openPage(id)
|
||||
}
|
||||
|
||||
override suspend fun closePage(id: String) {
|
||||
factory.remote.closePage(id)
|
||||
}
|
||||
|
@ -46,19 +46,35 @@ class BlockDataRepository(
|
|||
factory.remote.updateTextStyle(command.toEntity())
|
||||
}
|
||||
|
||||
override suspend fun updateTextColor(command: Command.UpdateTextColor) {
|
||||
factory.remote.updateTextColor(command.toEntity())
|
||||
}
|
||||
override suspend fun updateTextColor(
|
||||
command: Command.UpdateTextColor
|
||||
): Payload = factory.remote.updateTextColor(command.toEntity()).toDomain()
|
||||
|
||||
override suspend fun updateBackgroundColor(command: Command.UpdateBackgroundColor) {
|
||||
factory.remote.updateBackroundColor(command.toEntity())
|
||||
}
|
||||
override suspend fun updateBackgroundColor(
|
||||
command: Command.UpdateBackgroundColor
|
||||
): Payload = factory.remote.updateBackroundColor(command.toEntity()).toDomain()
|
||||
|
||||
override suspend fun updateCheckbox(command: Command.UpdateCheckbox) {
|
||||
factory.remote.updateCheckbox(command.toEntity())
|
||||
}
|
||||
|
||||
override suspend fun create(command: Command.Create) = factory.remote.create(command.toEntity())
|
||||
override suspend fun create(command: Command.Create): Pair<Id, Payload> {
|
||||
return factory.remote.create(command.toEntity()).let { (id, payload) ->
|
||||
Pair(id, payload.toDomain())
|
||||
}
|
||||
}
|
||||
|
||||
override suspend fun replace(
|
||||
command: Command.Replace
|
||||
): Pair<Id, Payload> = factory.remote.replace(command.toEntity()).let { (id, payload) ->
|
||||
Pair(id, payload.toDomain())
|
||||
}
|
||||
|
||||
override suspend fun duplicate(
|
||||
command: Command.Duplicate
|
||||
): Pair<Id, Payload> = factory.remote.duplicate(command.toEntity()).let { (id, payload) ->
|
||||
Pair(id, payload.toDomain())
|
||||
}
|
||||
|
||||
override suspend fun createDocument(
|
||||
command: Command.CreateDocument
|
||||
|
@ -68,19 +84,20 @@ class BlockDataRepository(
|
|||
factory.remote.dnd(command.toEntity())
|
||||
}
|
||||
|
||||
override suspend fun duplicate(command: Command.Duplicate) =
|
||||
factory.remote.duplicate(command.toEntity())
|
||||
override suspend fun unlink(
|
||||
command: Command.Unlink
|
||||
): Payload = factory.remote.unlink(command.toEntity()).toDomain()
|
||||
|
||||
override suspend fun unlink(command: Command.Unlink) {
|
||||
factory.remote.unlink(command.toEntity())
|
||||
override suspend fun merge(
|
||||
command: Command.Merge
|
||||
): Payload = factory.remote.merge(command.toEntity()).toDomain()
|
||||
|
||||
override suspend fun split(
|
||||
command: Command.Split
|
||||
): Pair<Id, Payload> = factory.remote.split(command.toEntity()).let { (id, payload) ->
|
||||
Pair(id, payload.toDomain())
|
||||
}
|
||||
|
||||
override suspend fun merge(command: Command.Merge) {
|
||||
factory.remote.merge(command.toEntity())
|
||||
}
|
||||
|
||||
override suspend fun split(command: Command.Split) = factory.remote.split(command.toEntity())
|
||||
|
||||
override suspend fun setIconName(
|
||||
command: Command.SetIconName
|
||||
) = factory.remote.setIconName(command.toEntity())
|
||||
|
@ -100,8 +117,4 @@ class BlockDataRepository(
|
|||
override suspend fun archiveDocument(
|
||||
command: Command.ArchiveDocument
|
||||
) = factory.remote.archiveDocument(command.toEntity())
|
||||
|
||||
override suspend fun replace(
|
||||
command: Command.Replace
|
||||
): Id = factory.remote.replace(command.toEntity())
|
||||
}
|
|
@ -2,34 +2,39 @@ package com.agileburo.anytype.data.auth.repo.block
|
|||
|
||||
import com.agileburo.anytype.data.auth.model.CommandEntity
|
||||
import com.agileburo.anytype.data.auth.model.ConfigEntity
|
||||
import com.agileburo.anytype.data.auth.model.PayloadEntity
|
||||
import com.agileburo.anytype.domain.common.Id
|
||||
|
||||
interface BlockDataStore {
|
||||
suspend fun create(command: CommandEntity.Create): Id
|
||||
|
||||
suspend fun create(command: CommandEntity.Create): Pair<Id, PayloadEntity>
|
||||
suspend fun replace(command: CommandEntity.Replace): Pair<Id, PayloadEntity>
|
||||
suspend fun duplicate(command: CommandEntity.Duplicate): Pair<Id, PayloadEntity>
|
||||
suspend fun split(command: CommandEntity.Split): Pair<Id, PayloadEntity>
|
||||
|
||||
suspend fun merge(command: CommandEntity.Merge): PayloadEntity
|
||||
suspend fun updateTextColor(command: CommandEntity.UpdateTextColor): PayloadEntity
|
||||
suspend fun updateBackroundColor(command: CommandEntity.UpdateBackgroundColor): PayloadEntity
|
||||
suspend fun updateAlignment(command: CommandEntity.UpdateAlignment) : PayloadEntity
|
||||
suspend fun openDashboard(contextId: String, id: String): PayloadEntity
|
||||
|
||||
suspend fun createDocument(command: CommandEntity.CreateDocument): Pair<Id, Id>
|
||||
suspend fun updateDocumentTitle(command: CommandEntity.UpdateTitle)
|
||||
suspend fun updateText(command: CommandEntity.UpdateText)
|
||||
suspend fun updateTextStyle(command: CommandEntity.UpdateStyle)
|
||||
suspend fun updateTextColor(command: CommandEntity.UpdateTextColor)
|
||||
suspend fun updateBackroundColor(command: CommandEntity.UpdateBackgroundColor)
|
||||
suspend fun updateAlignment(command: CommandEntity.UpdateAlignment)
|
||||
|
||||
suspend fun updateCheckbox(command: CommandEntity.UpdateCheckbox)
|
||||
suspend fun uploadUrl(command: CommandEntity.UploadBlock)
|
||||
suspend fun dnd(command: CommandEntity.Dnd)
|
||||
suspend fun duplicate(command: CommandEntity.Duplicate): Id
|
||||
suspend fun merge(command: CommandEntity.Merge)
|
||||
suspend fun split(command: CommandEntity.Split): Id
|
||||
suspend fun unlink(command: CommandEntity.Unlink)
|
||||
suspend fun unlink(command: CommandEntity.Unlink): PayloadEntity
|
||||
suspend fun getConfig(): ConfigEntity
|
||||
suspend fun createPage(parentId: String): String
|
||||
suspend fun openPage(id: String)
|
||||
suspend fun openPage(id: String): PayloadEntity
|
||||
suspend fun closePage(id: String)
|
||||
suspend fun openDashboard(contextId: String, id: String)
|
||||
suspend fun closeDashboard(id: String)
|
||||
suspend fun setIconName(command: CommandEntity.SetIconName)
|
||||
suspend fun setupBookmark(command: CommandEntity.SetupBookmark)
|
||||
suspend fun undo(command: CommandEntity.Undo)
|
||||
suspend fun redo(command: CommandEntity.Redo)
|
||||
suspend fun archiveDocument(command: CommandEntity.ArchiveDocument)
|
||||
suspend fun replace(command: CommandEntity.Replace): Id
|
||||
}
|
|
@ -2,28 +2,34 @@ package com.agileburo.anytype.data.auth.repo.block
|
|||
|
||||
import com.agileburo.anytype.data.auth.model.CommandEntity
|
||||
import com.agileburo.anytype.data.auth.model.ConfigEntity
|
||||
import com.agileburo.anytype.data.auth.model.PayloadEntity
|
||||
import com.agileburo.anytype.domain.common.Id
|
||||
|
||||
interface BlockRemote {
|
||||
suspend fun create(command: CommandEntity.Create): Id
|
||||
|
||||
suspend fun create(command: CommandEntity.Create): Pair<String, PayloadEntity>
|
||||
suspend fun replace(command: CommandEntity.Replace): Pair<String, PayloadEntity>
|
||||
suspend fun duplicate(command: CommandEntity.Duplicate): Pair<String, PayloadEntity>
|
||||
suspend fun split(command: CommandEntity.Split): Pair<Id, PayloadEntity>
|
||||
|
||||
suspend fun merge(command: CommandEntity.Merge): PayloadEntity
|
||||
suspend fun unlink(command: CommandEntity.Unlink): PayloadEntity
|
||||
suspend fun updateTextColor(command: CommandEntity.UpdateTextColor): PayloadEntity
|
||||
suspend fun updateBackgroundColor(command: CommandEntity.UpdateBackgroundColor): PayloadEntity
|
||||
suspend fun updateAlignment(command: CommandEntity.UpdateAlignment) : PayloadEntity
|
||||
|
||||
suspend fun createDocument(command: CommandEntity.CreateDocument): Pair<String, String>
|
||||
suspend fun updateDocumentTitle(command: CommandEntity.UpdateTitle)
|
||||
suspend fun updateText(command: CommandEntity.UpdateText)
|
||||
suspend fun updateTextStyle(command: CommandEntity.UpdateStyle)
|
||||
suspend fun updateTextColor(command: CommandEntity.UpdateTextColor)
|
||||
suspend fun updateBackgroundColor(command: CommandEntity.UpdateBackgroundColor)
|
||||
suspend fun updateAlignment(command: CommandEntity.UpdateAlignment)
|
||||
|
||||
suspend fun updateCheckbox(command: CommandEntity.UpdateCheckbox)
|
||||
suspend fun dnd(command: CommandEntity.Dnd)
|
||||
suspend fun merge(command: CommandEntity.Merge)
|
||||
suspend fun split(command: CommandEntity.Split): Id
|
||||
suspend fun duplicate(command: CommandEntity.Duplicate): Id
|
||||
suspend fun unlink(command: CommandEntity.Unlink)
|
||||
suspend fun getConfig(): ConfigEntity
|
||||
suspend fun createPage(parentId: String): String
|
||||
suspend fun openPage(id: String)
|
||||
suspend fun openPage(id: String): PayloadEntity
|
||||
suspend fun closePage(id: String)
|
||||
suspend fun openDashboard(contextId: String, id: String)
|
||||
suspend fun openDashboard(contextId: String, id: String): PayloadEntity
|
||||
suspend fun closeDashboard(id: String)
|
||||
suspend fun setIconName(command: CommandEntity.SetIconName)
|
||||
suspend fun uploadUrl(command: CommandEntity.UploadBlock)
|
||||
|
@ -31,5 +37,4 @@ interface BlockRemote {
|
|||
suspend fun undo(command: CommandEntity.Undo)
|
||||
suspend fun redo(command: CommandEntity.Redo)
|
||||
suspend fun archiveDocument(command: CommandEntity.ArchiveDocument)
|
||||
suspend fun replace(command: CommandEntity.Replace): Id
|
||||
}
|
|
@ -1,24 +1,24 @@
|
|||
package com.agileburo.anytype.data.auth.repo.block
|
||||
|
||||
import com.agileburo.anytype.data.auth.model.CommandEntity
|
||||
import com.agileburo.anytype.data.auth.model.PayloadEntity
|
||||
import com.agileburo.anytype.domain.common.Id
|
||||
|
||||
class BlockRemoteDataStore(private val remote: BlockRemote) : BlockDataStore {
|
||||
|
||||
override suspend fun getConfig() = remote.getConfig()
|
||||
|
||||
override suspend fun openDashboard(contextId: String, id: String) {
|
||||
remote.openDashboard(id = id, contextId = contextId)
|
||||
}
|
||||
override suspend fun openDashboard(
|
||||
contextId: String,
|
||||
id: String
|
||||
) = remote.openDashboard(id = id, contextId = contextId)
|
||||
|
||||
override suspend fun closeDashboard(id: String) {
|
||||
remote.closeDashboard(id = id)
|
||||
}
|
||||
|
||||
override suspend fun createPage(parentId: String): String = remote.createPage(parentId)
|
||||
override suspend fun openPage(id: String) {
|
||||
remote.openPage(id)
|
||||
}
|
||||
override suspend fun openPage(id: String): PayloadEntity = remote.openPage(id)
|
||||
|
||||
override suspend fun closePage(id: String) {
|
||||
remote.closePage(id)
|
||||
|
@ -36,27 +36,29 @@ class BlockRemoteDataStore(private val remote: BlockRemote) : BlockDataStore {
|
|||
remote.updateTextStyle(command)
|
||||
}
|
||||
|
||||
override suspend fun updateTextColor(command: CommandEntity.UpdateTextColor) {
|
||||
remote.updateTextColor(command)
|
||||
}
|
||||
override suspend fun updateTextColor(
|
||||
command: CommandEntity.UpdateTextColor
|
||||
): PayloadEntity = remote.updateTextColor(command)
|
||||
|
||||
override suspend fun updateBackroundColor(command: CommandEntity.UpdateBackgroundColor) {
|
||||
remote.updateBackgroundColor(command)
|
||||
}
|
||||
override suspend fun updateBackroundColor(
|
||||
command: CommandEntity.UpdateBackgroundColor
|
||||
): PayloadEntity = remote.updateBackgroundColor(command)
|
||||
|
||||
override suspend fun updateCheckbox(command: CommandEntity.UpdateCheckbox) {
|
||||
remote.updateCheckbox(command)
|
||||
}
|
||||
|
||||
override suspend fun updateAlignment(command: CommandEntity.UpdateAlignment) {
|
||||
remote.updateAlignment(command)
|
||||
}
|
||||
override suspend fun updateAlignment(
|
||||
command: CommandEntity.UpdateAlignment
|
||||
) : PayloadEntity = remote.updateAlignment(command)
|
||||
|
||||
override suspend fun uploadUrl(command: CommandEntity.UploadBlock) {
|
||||
remote.uploadUrl(command)
|
||||
}
|
||||
|
||||
override suspend fun create(command: CommandEntity.Create): String = remote.create(command)
|
||||
override suspend fun create(
|
||||
command: CommandEntity.Create
|
||||
): Pair<String, PayloadEntity> = remote.create(command)
|
||||
|
||||
override suspend fun createDocument(
|
||||
command: CommandEntity.CreateDocument
|
||||
|
@ -66,17 +68,21 @@ class BlockRemoteDataStore(private val remote: BlockRemote) : BlockDataStore {
|
|||
remote.dnd(command)
|
||||
}
|
||||
|
||||
override suspend fun duplicate(command: CommandEntity.Duplicate) = remote.duplicate(command)
|
||||
override suspend fun duplicate(
|
||||
command: CommandEntity.Duplicate
|
||||
): Pair<String, PayloadEntity> = remote.duplicate(command)
|
||||
|
||||
override suspend fun unlink(command: CommandEntity.Unlink) {
|
||||
remote.unlink(command)
|
||||
}
|
||||
override suspend fun unlink(
|
||||
command: CommandEntity.Unlink
|
||||
): PayloadEntity = remote.unlink(command)
|
||||
|
||||
override suspend fun merge(command: CommandEntity.Merge) {
|
||||
remote.merge(command)
|
||||
}
|
||||
override suspend fun merge(
|
||||
command: CommandEntity.Merge
|
||||
): PayloadEntity = remote.merge(command)
|
||||
|
||||
override suspend fun split(command: CommandEntity.Split): String = remote.split(command)
|
||||
override suspend fun split(
|
||||
command: CommandEntity.Split
|
||||
): Pair<String, PayloadEntity> = remote.split(command)
|
||||
|
||||
override suspend fun setIconName(
|
||||
command: CommandEntity.SetIconName
|
||||
|
@ -94,5 +100,6 @@ class BlockRemoteDataStore(private val remote: BlockRemote) : BlockDataStore {
|
|||
command: CommandEntity.ArchiveDocument
|
||||
) = remote.archiveDocument(command)
|
||||
|
||||
override suspend fun replace(command: CommandEntity.Replace): Id = remote.replace(command)
|
||||
override suspend fun replace(command: CommandEntity.Replace): Pair<Id, PayloadEntity> =
|
||||
remote.replace(command)
|
||||
}
|
|
@ -18,4 +18,12 @@ sealed class Either<out L, out R> {
|
|||
is Left -> fnL(a)
|
||||
is Right -> fnR(b)
|
||||
}
|
||||
|
||||
suspend fun proceed(
|
||||
failure: suspend (L) -> Any,
|
||||
success: suspend (R) -> Any
|
||||
): Any = when (this) {
|
||||
is Left -> failure(a)
|
||||
is Right -> success(b)
|
||||
}
|
||||
}
|
|
@ -8,6 +8,7 @@ import com.agileburo.anytype.domain.block.model.Command
|
|||
import com.agileburo.anytype.domain.block.model.Position
|
||||
import com.agileburo.anytype.domain.block.repo.BlockRepository
|
||||
import com.agileburo.anytype.domain.common.Id
|
||||
import com.agileburo.anytype.domain.event.model.Payload
|
||||
|
||||
/**
|
||||
* Use-case for creating a block.
|
||||
|
@ -15,7 +16,7 @@ import com.agileburo.anytype.domain.common.Id
|
|||
*/
|
||||
open class CreateBlock(
|
||||
private val repo: BlockRepository
|
||||
) : BaseUseCase<Id, Params>() {
|
||||
) : BaseUseCase<Pair<Id, Payload>, Params>() {
|
||||
|
||||
override suspend fun run(params: Params) = try {
|
||||
repo.create(
|
||||
|
|
|
@ -5,6 +5,7 @@ import com.agileburo.anytype.domain.base.Either
|
|||
import com.agileburo.anytype.domain.block.model.Command
|
||||
import com.agileburo.anytype.domain.block.repo.BlockRepository
|
||||
import com.agileburo.anytype.domain.common.Id
|
||||
import com.agileburo.anytype.domain.event.model.Payload
|
||||
|
||||
/**
|
||||
* Use-case for block duplication.
|
||||
|
@ -12,7 +13,7 @@ import com.agileburo.anytype.domain.common.Id
|
|||
*/
|
||||
open class DuplicateBlock(
|
||||
private val repo: BlockRepository
|
||||
) : BaseUseCase<Id, DuplicateBlock.Params>() {
|
||||
) : BaseUseCase<Pair<Id, Payload>, DuplicateBlock.Params>() {
|
||||
|
||||
override suspend fun run(params: Params) = try {
|
||||
repo.duplicate(
|
||||
|
|
|
@ -5,12 +5,13 @@ import com.agileburo.anytype.domain.base.Either
|
|||
import com.agileburo.anytype.domain.block.model.Command
|
||||
import com.agileburo.anytype.domain.block.repo.BlockRepository
|
||||
import com.agileburo.anytype.domain.common.Id
|
||||
import com.agileburo.anytype.domain.event.model.Payload
|
||||
|
||||
/**
|
||||
* Use-case for merging a pair of blocks.
|
||||
*/
|
||||
open class MergeBlocks(private val repo: BlockRepository) :
|
||||
BaseUseCase<Unit, MergeBlocks.Params>() {
|
||||
BaseUseCase<Payload, MergeBlocks.Params>() {
|
||||
|
||||
override suspend fun run(params: Params) = try {
|
||||
repo.merge(
|
||||
|
|
|
@ -6,13 +6,14 @@ import com.agileburo.anytype.domain.block.model.Block
|
|||
import com.agileburo.anytype.domain.block.model.Command
|
||||
import com.agileburo.anytype.domain.block.repo.BlockRepository
|
||||
import com.agileburo.anytype.domain.common.Id
|
||||
import com.agileburo.anytype.domain.event.model.Payload
|
||||
|
||||
/**
|
||||
* Use-case for replacing target block by a new block (created from prototype)
|
||||
*/
|
||||
class ReplaceBlock(
|
||||
private val repo: BlockRepository
|
||||
) : BaseUseCase<Id, ReplaceBlock.Params>() {
|
||||
) : BaseUseCase<Pair<Id, Payload>, ReplaceBlock.Params>() {
|
||||
|
||||
override suspend fun run(params: Params) = try {
|
||||
repo.replace(
|
||||
|
|
|
@ -5,11 +5,14 @@ import com.agileburo.anytype.domain.base.Either
|
|||
import com.agileburo.anytype.domain.block.model.Command
|
||||
import com.agileburo.anytype.domain.block.repo.BlockRepository
|
||||
import com.agileburo.anytype.domain.common.Id
|
||||
import com.agileburo.anytype.domain.event.model.Payload
|
||||
|
||||
/**
|
||||
* Use-case for splitting the target block into two blocks based on cursor position.
|
||||
*/
|
||||
class SplitBlock(private val repo: BlockRepository) : BaseUseCase<Id, SplitBlock.Params>() {
|
||||
class SplitBlock(
|
||||
private val repo: BlockRepository
|
||||
) : BaseUseCase<Pair<Id, Payload>, SplitBlock.Params>() {
|
||||
|
||||
override suspend fun run(params: Params) = try {
|
||||
repo.split(
|
||||
|
|
|
@ -5,13 +5,14 @@ import com.agileburo.anytype.domain.base.Either
|
|||
import com.agileburo.anytype.domain.block.model.Command
|
||||
import com.agileburo.anytype.domain.block.repo.BlockRepository
|
||||
import com.agileburo.anytype.domain.common.Id
|
||||
import com.agileburo.anytype.domain.event.model.Payload
|
||||
|
||||
/**
|
||||
* Use-case for unlinking blocks from its context.
|
||||
* Unlinking is a remplacement for delete operations.
|
||||
*/
|
||||
open class UnlinkBlocks(private val repo: BlockRepository) :
|
||||
BaseUseCase<Unit, UnlinkBlocks.Params>() {
|
||||
BaseUseCase<Payload, UnlinkBlocks.Params>() {
|
||||
|
||||
override suspend fun run(params: Params) = try {
|
||||
repo.unlink(
|
||||
|
|
|
@ -6,12 +6,13 @@ import com.agileburo.anytype.domain.block.model.Block
|
|||
import com.agileburo.anytype.domain.block.model.Command
|
||||
import com.agileburo.anytype.domain.block.repo.BlockRepository
|
||||
import com.agileburo.anytype.domain.common.Id
|
||||
import com.agileburo.anytype.domain.event.model.Payload
|
||||
|
||||
open class UpdateBlockAlignment(
|
||||
open class UpdateAlignment(
|
||||
private val repo: BlockRepository
|
||||
) : BaseUseCase<Unit, UpdateBlockAlignment.Params>() {
|
||||
) : BaseUseCase<Payload, UpdateAlignment.Params>() {
|
||||
|
||||
override suspend fun run(params: Params): Either<Throwable, Unit> = try {
|
||||
override suspend fun run(params: Params) = try {
|
||||
repo.updateAlignment(
|
||||
command = Command.UpdateAlignment(
|
||||
context = params.context,
|
|
@ -5,13 +5,14 @@ import com.agileburo.anytype.domain.base.Either
|
|||
import com.agileburo.anytype.domain.block.model.Command
|
||||
import com.agileburo.anytype.domain.block.repo.BlockRepository
|
||||
import com.agileburo.anytype.domain.common.Id
|
||||
import com.agileburo.anytype.domain.event.model.Payload
|
||||
|
||||
/**
|
||||
* Use-case for updating the whole block's text color.
|
||||
*/
|
||||
open class UpdateBackgroundColor(
|
||||
private val repo: BlockRepository
|
||||
) : BaseUseCase<Unit, UpdateBackgroundColor.Params>() {
|
||||
) : BaseUseCase<Payload, UpdateBackgroundColor.Params>() {
|
||||
|
||||
override suspend fun run(params: Params) = try {
|
||||
repo.updateBackgroundColor(
|
||||
|
|
|
@ -5,6 +5,7 @@ import com.agileburo.anytype.domain.base.Either
|
|||
import com.agileburo.anytype.domain.block.model.Block
|
||||
import com.agileburo.anytype.domain.block.model.Command
|
||||
import com.agileburo.anytype.domain.block.repo.BlockRepository
|
||||
import com.agileburo.anytype.domain.common.Id
|
||||
|
||||
open class UpdateText(
|
||||
private val repo: BlockRepository
|
||||
|
@ -13,8 +14,8 @@ open class UpdateText(
|
|||
override suspend fun run(params: Params) = try {
|
||||
repo.updateText(
|
||||
command = Command.UpdateText(
|
||||
contextId = params.contextId,
|
||||
blockId = params.blockId,
|
||||
contextId = params.context,
|
||||
blockId = params.target,
|
||||
text = params.text,
|
||||
marks = params.marks
|
||||
)
|
||||
|
@ -26,10 +27,9 @@ open class UpdateText(
|
|||
}
|
||||
|
||||
data class Params(
|
||||
val contextId: String,
|
||||
val blockId: String,
|
||||
val context: Id,
|
||||
val target: Id,
|
||||
val text: String,
|
||||
val marks: List<Block.Content.Text.Mark>
|
||||
)
|
||||
|
||||
}
|
|
@ -5,13 +5,14 @@ import com.agileburo.anytype.domain.base.Either
|
|||
import com.agileburo.anytype.domain.block.model.Command
|
||||
import com.agileburo.anytype.domain.block.repo.BlockRepository
|
||||
import com.agileburo.anytype.domain.common.Id
|
||||
import com.agileburo.anytype.domain.event.model.Payload
|
||||
|
||||
/**
|
||||
* Use-case for updating the whole block's text color.
|
||||
*/
|
||||
open class UpdateTextColor(
|
||||
private val repo: BlockRepository
|
||||
) : BaseUseCase<Unit, UpdateTextColor.Params>() {
|
||||
) : BaseUseCase<Payload, UpdateTextColor.Params>() {
|
||||
|
||||
override suspend fun run(params: Params) = try {
|
||||
repo.updateTextColor(
|
||||
|
|
|
@ -32,8 +32,6 @@ data class Block(
|
|||
val icon: String? by default
|
||||
val isArchived: Boolean? by default
|
||||
|
||||
fun hasName() = map.containsKey(NAME_KEY)
|
||||
|
||||
companion object {
|
||||
fun empty(): Fields = Fields(emptyMap())
|
||||
const val NAME_KEY = "name"
|
||||
|
@ -45,7 +43,7 @@ data class Block(
|
|||
* Document metadata
|
||||
* @property details maps id of the block to its details (contained as fields)
|
||||
*/
|
||||
data class Details(val details: Map<Id, Fields>)
|
||||
data class Details(val details: Map<Id, Fields> = emptyMap())
|
||||
|
||||
/**
|
||||
* Block's content.
|
||||
|
@ -58,6 +56,15 @@ data class Block(
|
|||
fun asDivider() = this as Divider
|
||||
fun asFile() = this as File
|
||||
|
||||
/**
|
||||
* Smart block.
|
||||
*/
|
||||
data class Smart(
|
||||
val type: Type
|
||||
) : Content() {
|
||||
enum class Type { HOME, PAGE, ARCHIVE, BREADCRUMBS, PROFILE }
|
||||
}
|
||||
|
||||
/**
|
||||
* Textual block.
|
||||
* @property text content text
|
||||
|
@ -124,7 +131,7 @@ data class Block(
|
|||
}
|
||||
|
||||
data class Layout(val type: Type) : Content() {
|
||||
enum class Type { ROW, COLUMN }
|
||||
enum class Type { ROW, COLUMN, DIV }
|
||||
}
|
||||
|
||||
data class Image(
|
||||
|
|
|
@ -3,19 +3,25 @@ package com.agileburo.anytype.domain.block.repo
|
|||
import com.agileburo.anytype.domain.block.model.Command
|
||||
import com.agileburo.anytype.domain.common.Id
|
||||
import com.agileburo.anytype.domain.config.Config
|
||||
import com.agileburo.anytype.domain.event.model.Payload
|
||||
|
||||
interface BlockRepository {
|
||||
suspend fun dnd(command: Command.Dnd)
|
||||
suspend fun duplicate(command: Command.Duplicate): Id
|
||||
suspend fun unlink(command: Command.Unlink)
|
||||
suspend fun unlink(command: Command.Unlink): Payload
|
||||
|
||||
suspend fun archiveDocument(command: Command.ArchiveDocument)
|
||||
|
||||
/**
|
||||
* Creates a new block.
|
||||
* @return id of the created block.
|
||||
* Duplicates target block
|
||||
* @return id of the new block and payload events.
|
||||
*/
|
||||
suspend fun create(command: Command.Create): Id
|
||||
suspend fun duplicate(command: Command.Duplicate): Pair<Id, Payload>
|
||||
|
||||
/**
|
||||
* Creates a new block.
|
||||
* @return id of the created block with event payload.
|
||||
*/
|
||||
suspend fun create(command: Command.Create): Pair<Id, Payload>
|
||||
|
||||
/**
|
||||
* Creates a new document / page.
|
||||
|
@ -23,37 +29,39 @@ interface BlockRepository {
|
|||
*/
|
||||
suspend fun createDocument(command: Command.CreateDocument): Pair<Id, Id>
|
||||
|
||||
suspend fun merge(command: Command.Merge)
|
||||
suspend fun merge(command: Command.Merge): Payload
|
||||
|
||||
/**
|
||||
* Splits one block into two blocks.
|
||||
* @return id of the block, created as a result of splitting.
|
||||
*/
|
||||
suspend fun split(command: Command.Split): Id
|
||||
suspend fun split(command: Command.Split): Pair<Id, Payload>
|
||||
|
||||
/**
|
||||
* Replaces target block by a new block (created from prototype).
|
||||
* @see Command.Replace for details
|
||||
* @return id of the new block
|
||||
*/
|
||||
suspend fun replace(command: Command.Replace): Id
|
||||
suspend fun replace(command: Command.Replace): Pair<Id, Payload>
|
||||
|
||||
suspend fun updateDocumentTitle(command: Command.UpdateTitle)
|
||||
suspend fun updateText(command: Command.UpdateText)
|
||||
suspend fun updateTextStyle(command: Command.UpdateStyle)
|
||||
suspend fun updateTextColor(command: Command.UpdateTextColor)
|
||||
suspend fun updateBackgroundColor(command: Command.UpdateBackgroundColor)
|
||||
|
||||
suspend fun updateTextColor(command: Command.UpdateTextColor): Payload
|
||||
suspend fun updateBackgroundColor(command: Command.UpdateBackgroundColor): Payload
|
||||
|
||||
suspend fun updateCheckbox(command: Command.UpdateCheckbox)
|
||||
suspend fun updateAlignment(command: Command.UpdateAlignment)
|
||||
suspend fun updateAlignment(command: Command.UpdateAlignment) : Payload
|
||||
|
||||
suspend fun getConfig(): Config
|
||||
|
||||
@Deprecated("Should be replaced by createDocument() command")
|
||||
suspend fun createPage(parentId: String): Id
|
||||
|
||||
suspend fun openPage(id: String)
|
||||
suspend fun openPage(id: String): Payload
|
||||
suspend fun closePage(id: String)
|
||||
suspend fun openDashboard(contextId: String, id: String)
|
||||
suspend fun openDashboard(contextId: String, id: String): Payload
|
||||
suspend fun closeDashboard(id: String)
|
||||
|
||||
/**
|
||||
|
|
|
@ -2,6 +2,7 @@ package com.agileburo.anytype.domain.dashboard.interactor
|
|||
|
||||
import com.agileburo.anytype.domain.block.model.Block
|
||||
import com.agileburo.anytype.domain.dashboard.model.HomeDashboard
|
||||
import com.agileburo.anytype.domain.ext.content
|
||||
|
||||
fun List<Block>.toHomeDashboard(
|
||||
id: String,
|
||||
|
@ -15,7 +16,7 @@ fun List<Block>.toHomeDashboard(
|
|||
},
|
||||
children = root.children,
|
||||
fields = root.fields,
|
||||
type = root.content.asDashboard().type,
|
||||
type = root.content<Block.Content.Smart>().type,
|
||||
details = details
|
||||
)
|
||||
}
|
|
@ -3,6 +3,7 @@ package com.agileburo.anytype.domain.dashboard.interactor
|
|||
import com.agileburo.anytype.domain.base.BaseUseCase
|
||||
import com.agileburo.anytype.domain.base.Either
|
||||
import com.agileburo.anytype.domain.block.repo.BlockRepository
|
||||
import com.agileburo.anytype.domain.event.model.Payload
|
||||
|
||||
/**
|
||||
* Use-case for opening a dashboard by sending a special request.
|
||||
|
@ -11,7 +12,7 @@ import com.agileburo.anytype.domain.block.repo.BlockRepository
|
|||
*/
|
||||
class OpenDashboard(
|
||||
private val repo: BlockRepository
|
||||
) : BaseUseCase<Unit, OpenDashboard.Param?>() {
|
||||
) : BaseUseCase<Payload, OpenDashboard.Param?>() {
|
||||
|
||||
override suspend fun run(params: Param?) = try {
|
||||
if (params != null)
|
||||
|
|
|
@ -7,6 +7,6 @@ data class HomeDashboard(
|
|||
val blocks: List<Block>,
|
||||
val children: List<String>,
|
||||
val fields: Block.Fields,
|
||||
val type: Block.Content.Dashboard.Type,
|
||||
val type: Block.Content.Smart.Type,
|
||||
val details: Block.Details = Block.Details(emptyMap())
|
||||
)
|
|
@ -0,0 +1,13 @@
|
|||
package com.agileburo.anytype.domain.event.model
|
||||
|
||||
import com.agileburo.anytype.domain.common.Id
|
||||
|
||||
/**
|
||||
* Represent events, as response to some command.
|
||||
* @param context id of the context
|
||||
* @param events new events, contained in response.
|
||||
*/
|
||||
data class Payload(
|
||||
val context: Id,
|
||||
val events: List<Event>
|
||||
)
|
|
@ -4,10 +4,11 @@ import com.agileburo.anytype.domain.base.BaseUseCase
|
|||
import com.agileburo.anytype.domain.base.Either
|
||||
import com.agileburo.anytype.domain.block.repo.BlockRepository
|
||||
import com.agileburo.anytype.domain.config.MainConfig
|
||||
import com.agileburo.anytype.domain.event.model.Payload
|
||||
|
||||
open class OpenPage(
|
||||
private val repo: BlockRepository
|
||||
) : BaseUseCase<Unit, OpenPage.Params>() {
|
||||
) : BaseUseCase<Payload, OpenPage.Params>() {
|
||||
|
||||
override suspend fun run(params: Params) = try {
|
||||
repo.openPage(params.id).let {
|
||||
|
@ -20,7 +21,7 @@ open class OpenPage(
|
|||
/**
|
||||
* @property id page's id
|
||||
*/
|
||||
class Params(val id: String) {
|
||||
data class Params(val id: String) {
|
||||
companion object {
|
||||
fun reference() = Params(id = MainConfig.REFERENCE_PAGE_ID)
|
||||
}
|
||||
|
|
|
@ -9,6 +9,7 @@ import com.agileburo.anytype.data.auth.model.BlockEntity
|
|||
import com.agileburo.anytype.data.auth.model.PositionEntity
|
||||
import com.google.protobuf.Struct
|
||||
import com.google.protobuf.Value
|
||||
import timber.log.Timber
|
||||
|
||||
|
||||
fun Events.Event.Account.Show.toAccountEntity(): AccountEntity {
|
||||
|
@ -95,6 +96,15 @@ fun Block.fields(): BlockEntity.Fields = BlockEntity.Fields().also { result ->
|
|||
}
|
||||
}
|
||||
|
||||
fun Events.SmartBlockType.entity(): BlockEntity.Content.Smart.Type = when (this) {
|
||||
Events.SmartBlockType.Archive -> BlockEntity.Content.Smart.Type.ARCHIVE
|
||||
Events.SmartBlockType.Page -> BlockEntity.Content.Smart.Type.PAGE
|
||||
Events.SmartBlockType.Breadcrumbs -> BlockEntity.Content.Smart.Type.BREADCRUMBS
|
||||
Events.SmartBlockType.Home -> BlockEntity.Content.Smart.Type.HOME
|
||||
Events.SmartBlockType.ProfilePage -> BlockEntity.Content.Smart.Type.PROFILE
|
||||
else -> throw IllegalStateException("Unexpected smart block type: $this")
|
||||
}
|
||||
|
||||
fun Struct.fields(): BlockEntity.Fields = BlockEntity.Fields().also { result ->
|
||||
fieldsMap.forEach { (key, value) ->
|
||||
result.map[key] = when (val case = value.kindCase) {
|
||||
|
@ -106,33 +116,6 @@ fun Struct.fields(): BlockEntity.Fields = BlockEntity.Fields().also { result ->
|
|||
}
|
||||
}
|
||||
|
||||
fun Block.dashboard(): BlockEntity.Content.Dashboard = BlockEntity.Content.Dashboard(
|
||||
type = when {
|
||||
dashboard.style == Block.Content.Dashboard.Style.Archive -> {
|
||||
BlockEntity.Content.Dashboard.Type.ARCHIVE
|
||||
}
|
||||
dashboard.style == Block.Content.Dashboard.Style.MainScreen -> {
|
||||
BlockEntity.Content.Dashboard.Type.MAIN_SCREEN
|
||||
}
|
||||
else -> throw IllegalStateException("Unexpected dashboard style: ${dashboard.style}")
|
||||
}
|
||||
)
|
||||
|
||||
fun Block.page(): BlockEntity.Content.Page = BlockEntity.Content.Page(
|
||||
style = when {
|
||||
page.style == Block.Content.Page.Style.Empty -> {
|
||||
BlockEntity.Content.Page.Style.EMPTY
|
||||
}
|
||||
page.style == Block.Content.Page.Style.Task -> {
|
||||
BlockEntity.Content.Page.Style.TASK
|
||||
}
|
||||
page.style == Block.Content.Page.Style.Set -> {
|
||||
BlockEntity.Content.Page.Style.SET
|
||||
}
|
||||
else -> throw IllegalStateException("Unexpected page style: ${page.style}")
|
||||
}
|
||||
)
|
||||
|
||||
fun Block.text(): BlockEntity.Content.Text = BlockEntity.Content.Text(
|
||||
text = text.text,
|
||||
marks = text.marks.marksList.marks(),
|
||||
|
@ -178,31 +161,20 @@ fun List<Block.Content.Text.Mark>.marks(): List<BlockEntity.Content.Text.Mark> =
|
|||
}
|
||||
|
||||
fun Block.layout(): BlockEntity.Content.Layout = BlockEntity.Content.Layout(
|
||||
type = when {
|
||||
layout.style == Block.Content.Layout.Style.Column -> {
|
||||
BlockEntity.Content.Layout.Type.COLUMN
|
||||
}
|
||||
layout.style == Block.Content.Layout.Style.Row -> {
|
||||
BlockEntity.Content.Layout.Type.ROW
|
||||
}
|
||||
type = when (layout.style) {
|
||||
Block.Content.Layout.Style.Column -> BlockEntity.Content.Layout.Type.COLUMN
|
||||
Block.Content.Layout.Style.Row -> BlockEntity.Content.Layout.Type.ROW
|
||||
Block.Content.Layout.Style.Div -> BlockEntity.Content.Layout.Type.DIV
|
||||
else -> throw IllegalStateException("Unexpected layout style: ${layout.style}")
|
||||
}
|
||||
)
|
||||
|
||||
fun Block.link(): BlockEntity.Content.Link = BlockEntity.Content.Link(
|
||||
type = when {
|
||||
link.style == Block.Content.Link.Style.Page -> {
|
||||
BlockEntity.Content.Link.Type.PAGE
|
||||
}
|
||||
link.style == Block.Content.Link.Style.Dataview -> {
|
||||
BlockEntity.Content.Link.Type.DATA_VIEW
|
||||
}
|
||||
link.style == Block.Content.Link.Style.Archive -> {
|
||||
BlockEntity.Content.Link.Type.ARCHIVE
|
||||
}
|
||||
link.style == Block.Content.Link.Style.Dashboard -> {
|
||||
BlockEntity.Content.Link.Type.DASHBOARD
|
||||
}
|
||||
type = when (link.style) {
|
||||
Block.Content.Link.Style.Page -> BlockEntity.Content.Link.Type.PAGE
|
||||
Block.Content.Link.Style.Dataview -> BlockEntity.Content.Link.Type.DATA_VIEW
|
||||
Block.Content.Link.Style.Archive -> BlockEntity.Content.Link.Type.ARCHIVE
|
||||
Block.Content.Link.Style.Dashboard -> BlockEntity.Content.Link.Type.DASHBOARD
|
||||
else -> throw IllegalStateException("Unexpected link style: ${link.style}")
|
||||
},
|
||||
target = link.targetBlockId,
|
||||
|
@ -264,24 +236,10 @@ fun Block.bookmark(): BlockEntity.Content.Bookmark = BlockEntity.Content.Bookmar
|
|||
favicon = bookmark.faviconHash.ifEmpty { null }
|
||||
)
|
||||
|
||||
fun List<Block>.blocks(): List<BlockEntity> = mapNotNull { block ->
|
||||
fun List<Block>.blocks(
|
||||
types: Map<String, Events.SmartBlockType> = emptyMap()
|
||||
): List<BlockEntity> = mapNotNull { block ->
|
||||
when (block.contentCase) {
|
||||
Block.ContentCase.DASHBOARD -> {
|
||||
BlockEntity(
|
||||
id = block.id,
|
||||
children = block.childrenIdsList.toList(),
|
||||
fields = block.fields(),
|
||||
content = block.dashboard()
|
||||
)
|
||||
}
|
||||
Block.ContentCase.PAGE -> {
|
||||
BlockEntity(
|
||||
id = block.id,
|
||||
children = block.childrenIdsList.toList(),
|
||||
fields = block.fields(),
|
||||
content = block.page()
|
||||
)
|
||||
}
|
||||
Block.ContentCase.TEXT -> {
|
||||
BlockEntity(
|
||||
id = block.id,
|
||||
|
@ -338,7 +296,18 @@ fun List<Block>.blocks(): List<BlockEntity> = mapNotNull { block ->
|
|||
content = block.bookmark()
|
||||
)
|
||||
}
|
||||
Block.ContentCase.SMARTBLOCK -> {
|
||||
BlockEntity(
|
||||
id = block.id,
|
||||
children = block.childrenIdsList,
|
||||
content = BlockEntity.Content.Smart(
|
||||
type = types[block.id]?.entity() ?: throw IllegalStateException("Type missing")
|
||||
),
|
||||
fields = block.fields()
|
||||
)
|
||||
}
|
||||
else -> {
|
||||
Timber.d("Ignoring content type: ${block.contentCase}")
|
||||
null
|
||||
}
|
||||
}
|
||||
|
|
|
@ -2,6 +2,7 @@ package com.agileburo.anytype.middleware.block
|
|||
|
||||
import com.agileburo.anytype.data.auth.model.CommandEntity
|
||||
import com.agileburo.anytype.data.auth.model.ConfigEntity
|
||||
import com.agileburo.anytype.data.auth.model.PayloadEntity
|
||||
import com.agileburo.anytype.data.auth.repo.block.BlockRemote
|
||||
import com.agileburo.anytype.middleware.interactor.Middleware
|
||||
import com.agileburo.anytype.middleware.toMiddleware
|
||||
|
@ -12,9 +13,10 @@ class BlockMiddleware(
|
|||
|
||||
override suspend fun getConfig(): ConfigEntity = middleware.config
|
||||
|
||||
override suspend fun openDashboard(contextId: String, id: String) {
|
||||
middleware.openDashboard(contextId, id)
|
||||
}
|
||||
override suspend fun openDashboard(
|
||||
contextId: String,
|
||||
id: String
|
||||
): PayloadEntity = middleware.openDashboard(contextId, id)
|
||||
|
||||
override suspend fun closeDashboard(id: String) {
|
||||
middleware.closeDashboard(id)
|
||||
|
@ -22,9 +24,7 @@ class BlockMiddleware(
|
|||
|
||||
override suspend fun createPage(parentId: String): String = middleware.createPage(parentId)
|
||||
|
||||
override suspend fun openPage(id: String) {
|
||||
middleware.openBlock(id)
|
||||
}
|
||||
override suspend fun openPage(id: String): PayloadEntity = middleware.openBlock(id)
|
||||
|
||||
override suspend fun closePage(id: String) {
|
||||
middleware.closePage(id)
|
||||
|
@ -51,17 +51,17 @@ class BlockMiddleware(
|
|||
middleware.updateTextStyle(command)
|
||||
}
|
||||
|
||||
override suspend fun updateTextColor(command: CommandEntity.UpdateTextColor) {
|
||||
middleware.updateTextColor(command)
|
||||
}
|
||||
override suspend fun updateTextColor(
|
||||
command: CommandEntity.UpdateTextColor
|
||||
): PayloadEntity = middleware.updateTextColor(command)
|
||||
|
||||
override suspend fun updateBackgroundColor(command: CommandEntity.UpdateBackgroundColor) {
|
||||
middleware.updateBackgroundColor(command)
|
||||
}
|
||||
override suspend fun updateBackgroundColor(
|
||||
command: CommandEntity.UpdateBackgroundColor
|
||||
): PayloadEntity = middleware.updateBackgroundColor(command)
|
||||
|
||||
override suspend fun updateAlignment(command: CommandEntity.UpdateAlignment) {
|
||||
middleware.updateAlignment(command)
|
||||
}
|
||||
override suspend fun updateAlignment(
|
||||
command: CommandEntity.UpdateAlignment
|
||||
) : PayloadEntity = middleware.updateAlignment(command)
|
||||
|
||||
override suspend fun updateCheckbox(command: CommandEntity.UpdateCheckbox) {
|
||||
middleware.updateCheckbox(
|
||||
|
@ -71,7 +71,9 @@ class BlockMiddleware(
|
|||
)
|
||||
}
|
||||
|
||||
override suspend fun create(command: CommandEntity.Create): String = middleware.createBlock(
|
||||
override suspend fun create(
|
||||
command: CommandEntity.Create
|
||||
): Pair<String, PayloadEntity> = middleware.createBlock(
|
||||
command.context,
|
||||
command.target,
|
||||
command.position,
|
||||
|
@ -82,22 +84,25 @@ class BlockMiddleware(
|
|||
command: CommandEntity.CreateDocument
|
||||
): Pair<String, String> = middleware.createDocument(command)
|
||||
|
||||
override suspend fun duplicate(
|
||||
command: CommandEntity.Duplicate
|
||||
): Pair<String, PayloadEntity> = middleware.duplicate(command)
|
||||
|
||||
override suspend fun dnd(command: CommandEntity.Dnd) {
|
||||
middleware.dnd(command)
|
||||
}
|
||||
|
||||
override suspend fun duplicate(command: CommandEntity.Duplicate): String =
|
||||
middleware.duplicate(command)
|
||||
override suspend fun unlink(
|
||||
command: CommandEntity.Unlink
|
||||
): PayloadEntity = middleware.unlink(command)
|
||||
|
||||
override suspend fun unlink(command: CommandEntity.Unlink) {
|
||||
middleware.unlink(command)
|
||||
}
|
||||
override suspend fun merge(
|
||||
command: CommandEntity.Merge
|
||||
): PayloadEntity = middleware.merge(command)
|
||||
|
||||
override suspend fun merge(command: CommandEntity.Merge) {
|
||||
middleware.merge(command)
|
||||
}
|
||||
|
||||
override suspend fun split(command: CommandEntity.Split): String = middleware.split(command)
|
||||
override suspend fun split(
|
||||
command: CommandEntity.Split
|
||||
): Pair<String, PayloadEntity> = middleware.split(command)
|
||||
|
||||
override suspend fun setIconName(
|
||||
command: CommandEntity.SetIconName
|
||||
|
@ -117,5 +122,5 @@ class BlockMiddleware(
|
|||
|
||||
override suspend fun replace(
|
||||
command: CommandEntity.Replace
|
||||
): String = middleware.replace(command)
|
||||
): Pair<String, PayloadEntity> = middleware.replace(command)
|
||||
}
|
|
@ -3,7 +3,9 @@ package com.agileburo.anytype.middleware.interactor;
|
|||
import com.agileburo.anytype.data.auth.model.BlockEntity;
|
||||
import com.agileburo.anytype.data.auth.model.CommandEntity;
|
||||
import com.agileburo.anytype.data.auth.model.ConfigEntity;
|
||||
import com.agileburo.anytype.data.auth.model.PayloadEntity;
|
||||
import com.agileburo.anytype.data.auth.model.PositionEntity;
|
||||
import com.agileburo.anytype.middleware.BuildConfig;
|
||||
import com.agileburo.anytype.middleware.model.CreateAccountResponse;
|
||||
import com.agileburo.anytype.middleware.model.CreateWalletResponse;
|
||||
import com.agileburo.anytype.middleware.model.SelectAccountResponse;
|
||||
|
@ -18,6 +20,7 @@ import anytype.Commands.Rpc.BlockList;
|
|||
import anytype.Commands.Rpc.Config;
|
||||
import anytype.Commands.Rpc.Wallet;
|
||||
import anytype.model.Models;
|
||||
import anytype.model.Models.Range;
|
||||
import kotlin.Pair;
|
||||
import timber.log.Timber;
|
||||
|
||||
|
@ -59,18 +62,24 @@ public class Middleware {
|
|||
}
|
||||
|
||||
public CreateAccountResponse createAccount(String name, String path) throws Exception {
|
||||
|
||||
Account.Create.Request request;
|
||||
|
||||
// TODO remove hard-coded alpha invite code when no longer needed
|
||||
String code = "elbrus";
|
||||
|
||||
if (path != null) {
|
||||
request = Account.Create.Request
|
||||
.newBuilder()
|
||||
.setName(name)
|
||||
.setAvatarLocalPath(path)
|
||||
.setAlphaInviteCode(code)
|
||||
.build();
|
||||
} else {
|
||||
request = Account.Create.Request
|
||||
.newBuilder()
|
||||
.setName(name)
|
||||
.setAlphaInviteCode(code)
|
||||
.build();
|
||||
}
|
||||
|
||||
|
@ -124,7 +133,7 @@ public class Middleware {
|
|||
);
|
||||
}
|
||||
|
||||
public void openDashboard(String contextId, String id) throws Exception {
|
||||
public PayloadEntity openDashboard(String contextId, String id) throws Exception {
|
||||
Block.Open.Request request = Block.Open.Request
|
||||
.newBuilder()
|
||||
.setContextId(contextId)
|
||||
|
@ -133,10 +142,12 @@ public class Middleware {
|
|||
|
||||
Timber.d("Opening home dashboard with the following request:\n%s", request.toString());
|
||||
|
||||
service.blockOpen(request);
|
||||
Block.Open.Response response = service.blockOpen(request);
|
||||
|
||||
return mapper.toPayload(response.getEvent());
|
||||
}
|
||||
|
||||
public void openBlock(String id) throws Exception {
|
||||
public PayloadEntity openBlock(String id) throws Exception {
|
||||
Block.Open.Request request = Block.Open.Request
|
||||
.newBuilder()
|
||||
.setBlockId(id)
|
||||
|
@ -144,7 +155,9 @@ public class Middleware {
|
|||
|
||||
Timber.d("Opening page with the following request:\n%s", request.toString());
|
||||
|
||||
service.blockOpen(request);
|
||||
Block.Open.Response response = service.blockOpen(request);
|
||||
|
||||
return mapper.toPayload(response.getEvent());
|
||||
}
|
||||
|
||||
public String createPage(String parentId) throws Exception {
|
||||
|
@ -258,7 +271,7 @@ public class Middleware {
|
|||
service.blockSetTextStyle(request);
|
||||
}
|
||||
|
||||
public void updateTextColor(CommandEntity.UpdateTextColor command) throws Exception {
|
||||
public PayloadEntity updateTextColor(CommandEntity.UpdateTextColor command) throws Exception {
|
||||
Block.Set.Text.Color.Request request = Block.Set.Text.Color.Request
|
||||
.newBuilder()
|
||||
.setContextId(command.getContext())
|
||||
|
@ -268,10 +281,12 @@ public class Middleware {
|
|||
|
||||
Timber.d("Updating text color with the following request:\n%s", request.toString());
|
||||
|
||||
service.blockSetTextColor(request);
|
||||
Block.Set.Text.Color.Response response = service.blockSetTextColor(request);
|
||||
|
||||
return mapper.toPayload(response.getEvent());
|
||||
}
|
||||
|
||||
public void updateBackgroundColor(CommandEntity.UpdateBackgroundColor command) throws Exception {
|
||||
public PayloadEntity updateBackgroundColor(CommandEntity.UpdateBackgroundColor command) throws Exception {
|
||||
BlockList.Set.BackgroundColor.Request request = BlockList.Set.BackgroundColor.Request
|
||||
.newBuilder()
|
||||
.setContextId(command.getContext())
|
||||
|
@ -281,10 +296,12 @@ public class Middleware {
|
|||
|
||||
Timber.d("Updating background color with the following request:\n%s", request.toString());
|
||||
|
||||
service.blockSetTextBackgroundColor(request);
|
||||
BlockList.Set.BackgroundColor.Response response = service.blockSetTextBackgroundColor(request);
|
||||
|
||||
return mapper.toPayload(response.getEvent());
|
||||
}
|
||||
|
||||
public void updateAlignment(CommandEntity.UpdateAlignment command) throws Exception {
|
||||
public PayloadEntity updateAlignment(CommandEntity.UpdateAlignment command) throws Exception {
|
||||
|
||||
Models.Block.Align align = mapper.toMiddleware(command.getAlignment());
|
||||
|
||||
|
@ -297,7 +314,9 @@ public class Middleware {
|
|||
|
||||
Timber.d("Updating alignment with the following request:\n%s", request.toString());
|
||||
|
||||
service.blockSetAlignment(request);
|
||||
BlockList.Set.Align.Response response = service.blockSetAlignment(request);
|
||||
|
||||
return mapper.toPayload(response.getEvent());
|
||||
}
|
||||
|
||||
public void uploadMediaBlockContent(CommandEntity.UploadBlock command) throws Exception {
|
||||
|
@ -314,7 +333,7 @@ public class Middleware {
|
|||
service.blockUpload(request);
|
||||
}
|
||||
|
||||
public String createBlock(
|
||||
public Pair<String, PayloadEntity> createBlock(
|
||||
String contextId,
|
||||
String targetId,
|
||||
PositionEntity position,
|
||||
|
@ -333,14 +352,20 @@ public class Middleware {
|
|||
.setBlock(model)
|
||||
.build();
|
||||
|
||||
Timber.d("Creating block with the following request:\n%s", request.toString());
|
||||
if (BuildConfig.DEBUG) {
|
||||
Timber.d(request.getClass().getName() + "\n" + request.toString());
|
||||
}
|
||||
|
||||
Block.Create.Response response = service.blockCreate(request);
|
||||
|
||||
return response.getBlockId();
|
||||
if (BuildConfig.DEBUG) {
|
||||
Timber.d(response.getClass().getName() + "\n" + response.toString());
|
||||
}
|
||||
|
||||
return new Pair<>(response.getBlockId(), mapper.toPayload(response.getEvent()));
|
||||
}
|
||||
|
||||
public String replace(CommandEntity.Replace command) throws Exception {
|
||||
public Pair<String, PayloadEntity> replace(CommandEntity.Replace command) throws Exception {
|
||||
Models.Block model = factory.create(command.getPrototype());
|
||||
|
||||
Block.Create.Request request = Block.Create.Request
|
||||
|
@ -351,11 +376,11 @@ public class Middleware {
|
|||
.setBlock(model)
|
||||
.build();
|
||||
|
||||
Timber.d("Replacing block with the following request:\n%s", request.toString());
|
||||
Timber.i("Replacing block with the following request:\n%s", request.toString());
|
||||
|
||||
Block.Create.Response response = service.blockCreate(request);
|
||||
|
||||
return response.getBlockId();
|
||||
return new Pair<>(response.getBlockId(), mapper.toPayload(response.getEvent()));
|
||||
}
|
||||
|
||||
public Pair<String, String> createDocument(CommandEntity.CreateDocument command) throws Exception {
|
||||
|
@ -390,7 +415,7 @@ public class Middleware {
|
|||
service.blockListMove(request);
|
||||
}
|
||||
|
||||
public String duplicate(CommandEntity.Duplicate command) throws Exception {
|
||||
public Pair<String, PayloadEntity> duplicate(CommandEntity.Duplicate command) throws Exception {
|
||||
BlockList.Duplicate.Request request = BlockList.Duplicate.Request
|
||||
.newBuilder()
|
||||
.setContextId(command.getContext())
|
||||
|
@ -403,10 +428,10 @@ public class Middleware {
|
|||
|
||||
BlockList.Duplicate.Response response = service.blockListDuplicate(request);
|
||||
|
||||
return response.getBlockIds(0);
|
||||
return new Pair<>(response.getBlockIds(0), mapper.toPayload(response.getEvent()));
|
||||
}
|
||||
|
||||
public void unlink(CommandEntity.Unlink command) throws Exception {
|
||||
public PayloadEntity unlink(CommandEntity.Unlink command) throws Exception {
|
||||
Block.Unlink.Request request = Block.Unlink.Request
|
||||
.newBuilder()
|
||||
.setContextId(command.getContext())
|
||||
|
@ -415,10 +440,12 @@ public class Middleware {
|
|||
|
||||
Timber.d("Unlinking blocks with the following request:\n%s", request.toString());
|
||||
|
||||
service.blockUnlink(request);
|
||||
Block.Unlink.Response response = service.blockUnlink(request);
|
||||
|
||||
return mapper.toPayload(response.getEvent());
|
||||
}
|
||||
|
||||
public void merge(CommandEntity.Merge command) throws Exception {
|
||||
public PayloadEntity merge(CommandEntity.Merge command) throws Exception {
|
||||
Block.Merge.Request request = Block.Merge.Request
|
||||
.newBuilder()
|
||||
.setContextId(command.getContext())
|
||||
|
@ -428,22 +455,31 @@ public class Middleware {
|
|||
|
||||
Timber.d("Merging blocks with the following request:\n%s", request.toString());
|
||||
|
||||
service.blockMerge(request);
|
||||
Block.Merge.Response response = service.blockMerge(request);
|
||||
|
||||
return mapper.toPayload(response.getEvent());
|
||||
}
|
||||
|
||||
public String split(CommandEntity.Split command) throws Exception {
|
||||
public Pair<String, PayloadEntity> split(CommandEntity.Split command) throws Exception {
|
||||
|
||||
Range range = Range
|
||||
.newBuilder()
|
||||
.setFrom(command.getIndex())
|
||||
.setTo(command.getIndex())
|
||||
.build();
|
||||
|
||||
Block.Split.Request request = Block.Split.Request
|
||||
.newBuilder()
|
||||
.setBlockId(command.getTarget())
|
||||
.setContextId(command.getContext())
|
||||
.setCursorPosition(command.getIndex())
|
||||
.setRange(range)
|
||||
.build();
|
||||
|
||||
Timber.d("Splitting the target block with the following request:\n%s", request.toString());
|
||||
|
||||
Block.Split.Response response = service.blockSplit(request);
|
||||
|
||||
return response.getBlockId();
|
||||
return new Pair<>(response.getBlockId(), mapper.toPayload(response.getEvent()));
|
||||
}
|
||||
|
||||
public void setIconName(CommandEntity.SetIconName command) throws Exception {
|
||||
|
|
|
@ -2,9 +2,8 @@ package com.agileburo.anytype.middleware.interactor
|
|||
|
||||
import anytype.Events
|
||||
import com.agileburo.anytype.data.auth.event.EventRemoteChannel
|
||||
import com.agileburo.anytype.data.auth.model.BlockEntity
|
||||
import com.agileburo.anytype.data.auth.model.EventEntity
|
||||
import com.agileburo.anytype.middleware.*
|
||||
import com.agileburo.anytype.middleware.EventProxy
|
||||
import kotlinx.coroutines.flow.Flow
|
||||
import kotlinx.coroutines.flow.filter
|
||||
import kotlinx.coroutines.flow.map
|
||||
|
@ -36,7 +35,7 @@ class MiddlewareEventChannel(
|
|||
context: String?
|
||||
): Flow<List<EventEntity>> = events
|
||||
.flow()
|
||||
.filter { context == null || it.contextId == context }
|
||||
.filter { event -> context == null || event.contextId == context }
|
||||
.map { event ->
|
||||
event.messagesList.filter { message ->
|
||||
supportedEvents.contains(message.valueCase)
|
||||
|
@ -46,140 +45,6 @@ class MiddlewareEventChannel(
|
|||
.map { events -> processEvents(events) }
|
||||
|
||||
private fun processEvents(events: List<Pair<String, Events.Event.Message>>): List<EventEntity.Command> {
|
||||
return events.mapNotNull { (context, event) ->
|
||||
when (event.valueCase) {
|
||||
Events.Event.Message.ValueCase.BLOCKADD -> {
|
||||
EventEntity.Command.AddBlock(
|
||||
context = context,
|
||||
blocks = event.blockAdd.blocksList.blocks()
|
||||
)
|
||||
}
|
||||
Events.Event.Message.ValueCase.BLOCKSHOW -> {
|
||||
EventEntity.Command.ShowBlock(
|
||||
context = context,
|
||||
root = event.blockShow.rootId,
|
||||
blocks = event.blockShow.blocksList.blocks(),
|
||||
details = BlockEntity.Details(
|
||||
event.blockShow.detailsList.associate { details ->
|
||||
details.id to details.details.fields()
|
||||
}
|
||||
)
|
||||
)
|
||||
}
|
||||
Events.Event.Message.ValueCase.BLOCKSETTEXT -> {
|
||||
EventEntity.Command.GranularChange(
|
||||
context = context,
|
||||
id = event.blockSetText.id,
|
||||
text = if (event.blockSetText.hasText())
|
||||
event.blockSetText.text.value
|
||||
else null,
|
||||
style = if (event.blockSetText.hasStyle())
|
||||
event.blockSetText.style.value.entity()
|
||||
else
|
||||
null,
|
||||
color = if (event.blockSetText.hasColor())
|
||||
event.blockSetText.color.value
|
||||
else
|
||||
null,
|
||||
marks = if (event.blockSetText.hasMarks())
|
||||
event.blockSetText.marks.value.marksList.marks()
|
||||
else
|
||||
null
|
||||
)
|
||||
}
|
||||
Events.Event.Message.ValueCase.BLOCKSETBACKGROUNDCOLOR -> {
|
||||
EventEntity.Command.GranularChange(
|
||||
context = context,
|
||||
id = event.blockSetBackgroundColor.id,
|
||||
backgroundColor = event.blockSetBackgroundColor.backgroundColor
|
||||
)
|
||||
}
|
||||
Events.Event.Message.ValueCase.BLOCKSETALIGN -> {
|
||||
EventEntity.Command.GranularChange(
|
||||
context = context,
|
||||
id = event.blockSetAlign.id,
|
||||
alignment = event.blockSetAlign.align.entity()
|
||||
)
|
||||
}
|
||||
Events.Event.Message.ValueCase.BLOCKDELETE -> {
|
||||
EventEntity.Command.DeleteBlock(
|
||||
context = context,
|
||||
targets = event.blockDelete.blockIdsList.toList()
|
||||
)
|
||||
}
|
||||
Events.Event.Message.ValueCase.BLOCKSETCHILDRENIDS -> {
|
||||
EventEntity.Command.UpdateStructure(
|
||||
context = context,
|
||||
id = event.blockSetChildrenIds.id,
|
||||
children = event.blockSetChildrenIds.childrenIdsList.toList()
|
||||
)
|
||||
}
|
||||
Events.Event.Message.ValueCase.BLOCKSETDETAILS -> {
|
||||
EventEntity.Command.UpdateDetails(
|
||||
context = context,
|
||||
target = event.blockSetDetails.id,
|
||||
details = event.blockSetDetails.details.fields()
|
||||
)
|
||||
}
|
||||
Events.Event.Message.ValueCase.BLOCKSETLINK -> {
|
||||
EventEntity.Command.LinkGranularChange(
|
||||
context = context,
|
||||
id = event.blockSetLink.id,
|
||||
target = event.blockSetLink.targetBlockId.value,
|
||||
fields = if (event.blockSetLink.hasFields())
|
||||
event.blockSetLink.fields.value.fields()
|
||||
else
|
||||
null
|
||||
)
|
||||
}
|
||||
Events.Event.Message.ValueCase.BLOCKSETFIELDS -> {
|
||||
EventEntity.Command.UpdateFields(
|
||||
context = context,
|
||||
target = event.blockSetFields.id,
|
||||
fields = event.blockSetFields.fields.fields()
|
||||
)
|
||||
}
|
||||
Events.Event.Message.ValueCase.BLOCKSETFILE -> {
|
||||
with(event.blockSetFile) {
|
||||
EventEntity.Command.UpdateBlockFile(
|
||||
context = context,
|
||||
id = id,
|
||||
state = if (hasState()) state.value.entity() else null,
|
||||
type = if (hasType()) type.value.entity() else null,
|
||||
name = if (hasName()) name.value else null,
|
||||
hash = if (hasHash()) hash.value else null,
|
||||
mime = if (hasMime()) mime.value else null,
|
||||
size = if (hasSize()) size.value else null
|
||||
)
|
||||
}
|
||||
}
|
||||
Events.Event.Message.ValueCase.BLOCKSETBOOKMARK -> {
|
||||
EventEntity.Command.BookmarkGranularChange(
|
||||
context = context,
|
||||
target = event.blockSetBookmark.id,
|
||||
url = if (event.blockSetBookmark.hasUrl())
|
||||
event.blockSetBookmark.url.value
|
||||
else null,
|
||||
title = if (event.blockSetBookmark.hasTitle())
|
||||
event.blockSetBookmark.title.value
|
||||
else
|
||||
null,
|
||||
description = if (event.blockSetBookmark.hasDescription())
|
||||
event.blockSetBookmark.description.value
|
||||
else
|
||||
null,
|
||||
imageHash = if (event.blockSetBookmark.hasImageHash())
|
||||
event.blockSetBookmark.imageHash.value
|
||||
else
|
||||
null,
|
||||
faviconHash = if (event.blockSetBookmark.hasFaviconHash())
|
||||
event.blockSetBookmark.faviconHash.value
|
||||
else
|
||||
null
|
||||
)
|
||||
}
|
||||
else -> null
|
||||
}
|
||||
}
|
||||
return events.mapNotNull { (context, event) -> event.toEntity(context) }
|
||||
}
|
||||
}
|
|
@ -0,0 +1,147 @@
|
|||
package com.agileburo.anytype.middleware.interactor
|
||||
|
||||
import anytype.Events.Event
|
||||
import com.agileburo.anytype.data.auth.model.BlockEntity
|
||||
import com.agileburo.anytype.data.auth.model.EventEntity
|
||||
import com.agileburo.anytype.middleware.blocks
|
||||
import com.agileburo.anytype.middleware.entity
|
||||
import com.agileburo.anytype.middleware.fields
|
||||
import com.agileburo.anytype.middleware.marks
|
||||
|
||||
fun Event.Message.toEntity(
|
||||
context: String
|
||||
): EventEntity.Command? = when (valueCase) {
|
||||
Event.Message.ValueCase.BLOCKADD -> {
|
||||
EventEntity.Command.AddBlock(
|
||||
context = context,
|
||||
blocks = blockAdd.blocksList.blocks()
|
||||
)
|
||||
}
|
||||
Event.Message.ValueCase.BLOCKSHOW -> {
|
||||
EventEntity.Command.ShowBlock(
|
||||
context = context,
|
||||
root = blockShow.rootId,
|
||||
blocks = blockShow.blocksList.blocks(
|
||||
types = mapOf(blockShow.rootId to blockShow.type)
|
||||
),
|
||||
details = BlockEntity.Details(
|
||||
blockShow.detailsList.associate { details ->
|
||||
details.id to details.details.fields()
|
||||
}
|
||||
)
|
||||
)
|
||||
}
|
||||
Event.Message.ValueCase.BLOCKSETTEXT -> {
|
||||
EventEntity.Command.GranularChange(
|
||||
context = context,
|
||||
id = blockSetText.id,
|
||||
text = if (blockSetText.hasText())
|
||||
blockSetText.text.value
|
||||
else null,
|
||||
style = if (blockSetText.hasStyle())
|
||||
blockSetText.style.value.entity()
|
||||
else
|
||||
null,
|
||||
color = if (blockSetText.hasColor())
|
||||
blockSetText.color.value
|
||||
else
|
||||
null,
|
||||
marks = if (blockSetText.hasMarks())
|
||||
blockSetText.marks.value.marksList.marks()
|
||||
else
|
||||
null
|
||||
)
|
||||
}
|
||||
Event.Message.ValueCase.BLOCKSETBACKGROUNDCOLOR -> {
|
||||
EventEntity.Command.GranularChange(
|
||||
context = context,
|
||||
id = blockSetBackgroundColor.id,
|
||||
backgroundColor = blockSetBackgroundColor.backgroundColor
|
||||
)
|
||||
}
|
||||
Event.Message.ValueCase.BLOCKDELETE -> {
|
||||
EventEntity.Command.DeleteBlock(
|
||||
context = context,
|
||||
targets = blockDelete.blockIdsList.toList()
|
||||
)
|
||||
}
|
||||
Event.Message.ValueCase.BLOCKSETCHILDRENIDS -> {
|
||||
EventEntity.Command.UpdateStructure(
|
||||
context = context,
|
||||
id = blockSetChildrenIds.id,
|
||||
children = blockSetChildrenIds.childrenIdsList.toList()
|
||||
)
|
||||
}
|
||||
Event.Message.ValueCase.BLOCKSETDETAILS -> {
|
||||
EventEntity.Command.UpdateDetails(
|
||||
context = context,
|
||||
target = blockSetDetails.id,
|
||||
details = blockSetDetails.details.fields()
|
||||
)
|
||||
}
|
||||
Event.Message.ValueCase.BLOCKSETLINK -> {
|
||||
EventEntity.Command.LinkGranularChange(
|
||||
context = context,
|
||||
id = blockSetLink.id,
|
||||
target = blockSetLink.targetBlockId.value,
|
||||
fields = if (blockSetLink.hasFields())
|
||||
blockSetLink.fields.value.fields()
|
||||
else
|
||||
null
|
||||
)
|
||||
}
|
||||
Event.Message.ValueCase.BLOCKSETALIGN -> {
|
||||
EventEntity.Command.GranularChange(
|
||||
context = context,
|
||||
id = blockSetAlign.id,
|
||||
alignment = blockSetAlign.align.entity()
|
||||
)
|
||||
}
|
||||
Event.Message.ValueCase.BLOCKSETFIELDS -> {
|
||||
EventEntity.Command.UpdateFields(
|
||||
context = context,
|
||||
target = blockSetFields.id,
|
||||
fields = blockSetFields.fields.fields()
|
||||
)
|
||||
}
|
||||
Event.Message.ValueCase.BLOCKSETFILE -> {
|
||||
with(blockSetFile) {
|
||||
EventEntity.Command.UpdateBlockFile(
|
||||
context = context,
|
||||
id = id,
|
||||
state = if (hasState()) state.value.entity() else null,
|
||||
type = if (hasType()) type.value.entity() else null,
|
||||
name = if (hasName()) name.value else null,
|
||||
hash = if (hasHash()) hash.value else null,
|
||||
mime = if (hasMime()) mime.value else null,
|
||||
size = if (hasSize()) size.value else null
|
||||
)
|
||||
}
|
||||
}
|
||||
Event.Message.ValueCase.BLOCKSETBOOKMARK -> {
|
||||
EventEntity.Command.BookmarkGranularChange(
|
||||
context = context,
|
||||
target = blockSetBookmark.id,
|
||||
url = if (blockSetBookmark.hasUrl())
|
||||
blockSetBookmark.url.value
|
||||
else null,
|
||||
title = if (blockSetBookmark.hasTitle())
|
||||
blockSetBookmark.title.value
|
||||
else
|
||||
null,
|
||||
description = if (blockSetBookmark.hasDescription())
|
||||
blockSetBookmark.description.value
|
||||
else
|
||||
null,
|
||||
imageHash = if (blockSetBookmark.hasImageHash())
|
||||
blockSetBookmark.imageHash.value
|
||||
else
|
||||
null,
|
||||
faviconHash = if (blockSetBookmark.hasFaviconHash())
|
||||
blockSetBookmark.faviconHash.value
|
||||
else
|
||||
null
|
||||
)
|
||||
}
|
||||
else -> null
|
||||
}
|
|
@ -34,12 +34,7 @@ class MiddlewareFactory {
|
|||
}
|
||||
builder.setFile(file).build()
|
||||
}
|
||||
is BlockEntity.Prototype.Page -> {
|
||||
val page = Block.Content.Page.newBuilder().apply {
|
||||
style = Block.Content.Page.Style.Empty
|
||||
}
|
||||
builder.setPage(page).build()
|
||||
}
|
||||
else -> throw IllegalStateException("Unexpected prototype: $prototype")
|
||||
}
|
||||
}
|
||||
}
|
|
@ -1,7 +1,9 @@
|
|||
package com.agileburo.anytype.middleware.interactor
|
||||
|
||||
import anytype.Events
|
||||
import anytype.model.Models.Block
|
||||
import com.agileburo.anytype.data.auth.model.BlockEntity
|
||||
import com.agileburo.anytype.data.auth.model.PayloadEntity
|
||||
import com.agileburo.anytype.data.auth.model.PositionEntity
|
||||
import com.agileburo.anytype.middleware.toMiddleware
|
||||
|
||||
|
@ -15,6 +17,16 @@ class MiddlewareMapper {
|
|||
return position.toMiddleware()
|
||||
}
|
||||
|
||||
fun toPayload(response: Events.ResponseEvent): PayloadEntity {
|
||||
|
||||
val context = response.contextId
|
||||
|
||||
return PayloadEntity(
|
||||
context = context,
|
||||
events = response.messagesList.mapNotNull { it.toEntity(context) }
|
||||
)
|
||||
}
|
||||
|
||||
fun toMiddleware(alignment: BlockEntity.Align): Block.Align {
|
||||
return alignment.toMiddleware()
|
||||
}
|
||||
|
|
|
@ -131,7 +131,7 @@ class MiddlewareTest {
|
|||
|
||||
assertEquals(
|
||||
expected = response.blockId,
|
||||
actual = result
|
||||
actual = result.first
|
||||
)
|
||||
}
|
||||
|
||||
|
|
1
presentation-editor/.gitignore
vendored
Normal file
1
presentation-editor/.gitignore
vendored
Normal file
|
@ -0,0 +1 @@
|
|||
/build
|
55
presentation-editor/build.gradle
Normal file
55
presentation-editor/build.gradle
Normal file
|
@ -0,0 +1,55 @@
|
|||
apply plugin: 'com.android.library'
|
||||
apply plugin: 'kotlin-android'
|
||||
apply plugin: 'kotlin-android-extensions'
|
||||
apply plugin: 'kotlin-kapt'
|
||||
|
||||
|
||||
android {
|
||||
def config = rootProject.extensions.getByName("ext")
|
||||
compileSdkVersion config["compile_sdk"]
|
||||
|
||||
defaultConfig {
|
||||
minSdkVersion config["min_sdk"]
|
||||
targetSdkVersion config["target_sdk"]
|
||||
testInstrumentationRunner config["test_runner"]
|
||||
}
|
||||
|
||||
testOptions.unitTests.includeAndroidResources = true
|
||||
|
||||
androidExtensions {
|
||||
experimental = true
|
||||
}
|
||||
}
|
||||
|
||||
dependencies {
|
||||
|
||||
implementation project(':domain')
|
||||
implementation project(':core-utils')
|
||||
implementation project(':core-ui')
|
||||
implementation project(':library-page-icon-picker-widget')
|
||||
|
||||
def applicationDependencies = rootProject.ext.mainApplication
|
||||
def unitTestDependencies = rootProject.ext.unitTesting
|
||||
def lib = rootProject.ext.libraryPageIconPicker
|
||||
|
||||
implementation(lib.emojiJava) {
|
||||
exclude group: 'org.json', module: 'json'
|
||||
}
|
||||
|
||||
implementation applicationDependencies.kotlin
|
||||
implementation applicationDependencies.coroutines
|
||||
|
||||
implementation applicationDependencies.viewModel
|
||||
implementation applicationDependencies.viewModelExtensions
|
||||
|
||||
implementation applicationDependencies.timber
|
||||
|
||||
testImplementation unitTestDependencies.junit
|
||||
testImplementation unitTestDependencies.kotlinTest
|
||||
testImplementation unitTestDependencies.mockitoKotlin
|
||||
testImplementation unitTestDependencies.coroutineTesting
|
||||
testImplementation unitTestDependencies.liveDataTesting
|
||||
testImplementation unitTestDependencies.archCoreTesting
|
||||
|
||||
androidTestImplementation 'androidx.test:core:1.2.0'
|
||||
}
|
0
presentation-editor/consumer-rules.pro
Normal file
0
presentation-editor/consumer-rules.pro
Normal file
21
presentation-editor/proguard-rules.pro
vendored
Normal file
21
presentation-editor/proguard-rules.pro
vendored
Normal file
|
@ -0,0 +1,21 @@
|
|||
# Add project specific ProGuard rules here.
|
||||
# You can control the set of applied configuration files using the
|
||||
# proguardFiles setting in build.gradle.
|
||||
#
|
||||
# For more details, see
|
||||
# http://developer.android.com/guide/developing/tools/proguard.html
|
||||
|
||||
# If your project uses WebView with JS, uncomment the following
|
||||
# and specify the fully qualified class name to the JavaScript interface
|
||||
# class:
|
||||
#-keepclassmembers class fqcn.of.javascript.interface.for.webview {
|
||||
# public *;
|
||||
#}
|
||||
|
||||
# Uncomment this to preserve the line number information for
|
||||
# debugging stack traces.
|
||||
#-keepattributes SourceFile,LineNumberTable
|
||||
|
||||
# If you keep the line number information, uncomment this to
|
||||
# hide the original source file name.
|
||||
#-renamesourcefileattribute SourceFile
|
1
presentation-editor/src/main/AndroidManifest.xml
Normal file
1
presentation-editor/src/main/AndroidManifest.xml
Normal file
|
@ -0,0 +1 @@
|
|||
<manifest package="com.agileburo.anytype.presentation_editor" />
|
|
@ -0,0 +1,36 @@
|
|||
package com.agileburo.anytype.presentation.desktop
|
||||
|
||||
import com.agileburo.anytype.domain.dashboard.interactor.toHomeDashboard
|
||||
import com.agileburo.anytype.domain.event.model.Event
|
||||
|
||||
interface HomeDashboardEventConverter {
|
||||
|
||||
fun convert(event: Event): HomeDashboardStateMachine.Event?
|
||||
|
||||
class DefaultConverter : HomeDashboardEventConverter {
|
||||
|
||||
override fun convert(event: Event) = when (event) {
|
||||
is Event.Command.UpdateStructure -> HomeDashboardStateMachine.Event.OnStructureUpdated(
|
||||
event.children
|
||||
)
|
||||
is Event.Command.AddBlock -> HomeDashboardStateMachine.Event.OnBlocksAdded(
|
||||
event.blocks
|
||||
)
|
||||
is Event.Command.ShowBlock -> HomeDashboardStateMachine.Event.OnDashboardLoaded(
|
||||
dashboard = event.blocks.toHomeDashboard(
|
||||
id = event.context,
|
||||
details = event.details
|
||||
)
|
||||
)
|
||||
is Event.Command.LinkGranularChange -> {
|
||||
event.fields?.let { fields ->
|
||||
HomeDashboardStateMachine.Event.OnLinkFieldsChanged(
|
||||
id = event.id,
|
||||
fields = fields
|
||||
)
|
||||
}
|
||||
}
|
||||
else -> null
|
||||
}
|
||||
}
|
||||
}
|
|
@ -14,7 +14,6 @@ import com.agileburo.anytype.domain.block.model.Position
|
|||
import com.agileburo.anytype.domain.config.GetConfig
|
||||
import com.agileburo.anytype.domain.dashboard.interactor.CloseDashboard
|
||||
import com.agileburo.anytype.domain.dashboard.interactor.OpenDashboard
|
||||
import com.agileburo.anytype.domain.dashboard.interactor.toHomeDashboard
|
||||
import com.agileburo.anytype.domain.event.interactor.InterceptEvents
|
||||
import com.agileburo.anytype.domain.event.model.Event
|
||||
import com.agileburo.anytype.domain.image.LoadImage
|
||||
|
@ -38,8 +37,10 @@ class HomeDashboardViewModel(
|
|||
private val createPage: CreatePage,
|
||||
private val getConfig: GetConfig,
|
||||
private val dragAndDrop: DragAndDrop,
|
||||
private val interceptEvents: InterceptEvents
|
||||
private val interceptEvents: InterceptEvents,
|
||||
private val eventConverter: HomeDashboardEventConverter
|
||||
) : ViewStateViewModel<State>(),
|
||||
HomeDashboardEventConverter by eventConverter,
|
||||
SupportNavigation<EventWrapper<AppNavigation.Command>> {
|
||||
|
||||
private val machine = Interactor(scope = viewModelScope)
|
||||
|
@ -67,55 +68,19 @@ class HomeDashboardViewModel(
|
|||
}
|
||||
|
||||
private fun startInterceptingEvents(context: String) {
|
||||
// TODO use context when middleware is ready
|
||||
interceptEvents
|
||||
.build(InterceptEvents.Params(context = null))
|
||||
.build(InterceptEvents.Params(context = context))
|
||||
.onEach { Timber.d("New events: $it") }
|
||||
.onEach { events ->
|
||||
events.forEach { event ->
|
||||
when (event) {
|
||||
is Event.Command.UpdateStructure -> machine.onEvent(
|
||||
Machine.Event.OnStructureUpdated(
|
||||
event.children
|
||||
)
|
||||
)
|
||||
is Event.Command.AddBlock -> machine.onEvent(
|
||||
Machine.Event.OnBlocksAdded(
|
||||
event.blocks
|
||||
)
|
||||
)
|
||||
is Event.Command.ShowBlock -> {
|
||||
if (event.root == context) {
|
||||
machine.onEvent(
|
||||
Machine.Event.OnDashboardLoaded(
|
||||
dashboard = event.blocks.toHomeDashboard(
|
||||
id = context,
|
||||
details = event.details
|
||||
)
|
||||
)
|
||||
)
|
||||
} else {
|
||||
Timber.e("Receiving event from other context!")
|
||||
}
|
||||
}
|
||||
is Event.Command.LinkGranularChange -> {
|
||||
event.fields?.let { fields ->
|
||||
machine.onEvent(
|
||||
Machine.Event.OnLinkFieldsChanged(
|
||||
id = event.id,
|
||||
fields = fields
|
||||
)
|
||||
)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
.onEach { events -> processEvents(events) }
|
||||
.launchIn(viewModelScope)
|
||||
}
|
||||
|
||||
private fun processEvents(events: List<Event>) = events.forEach {
|
||||
convert(it)?.let { result -> machine.onEvent(result) }
|
||||
}
|
||||
|
||||
private fun proceedWithGettingConfig() {
|
||||
getConfig.invoke(viewModelScope, Unit) { result ->
|
||||
getConfig(viewModelScope, Unit) { result ->
|
||||
result.either(
|
||||
fnR = { config ->
|
||||
startInterceptingEvents(context = config.home)
|
||||
|
@ -127,7 +92,7 @@ class HomeDashboardViewModel(
|
|||
}
|
||||
|
||||
private fun proceedWithGettingAccount() {
|
||||
getCurrentAccount.invoke(viewModelScope, BaseUseCase.None) { result ->
|
||||
getCurrentAccount(viewModelScope, BaseUseCase.None) { result ->
|
||||
result.either(
|
||||
fnL = { Timber.e(it, "Error while getting account") },
|
||||
fnR = { account ->
|
||||
|
@ -153,7 +118,7 @@ class HomeDashboardViewModel(
|
|||
)
|
||||
}
|
||||
.collect { param ->
|
||||
dragAndDrop.invoke(this, param) { result ->
|
||||
dragAndDrop(viewModelScope, param) { result ->
|
||||
result.either(
|
||||
fnL = { Timber.e(it, "Error while DND for: $param") },
|
||||
fnR = { Timber.d("Successfull DND for: $param") }
|
||||
|
@ -164,16 +129,15 @@ class HomeDashboardViewModel(
|
|||
}
|
||||
|
||||
private fun proceedWithOpeningHomeDashboard() {
|
||||
|
||||
machine.onEvent(Machine.Event.OnDashboardLoadingStarted)
|
||||
|
||||
Timber.d("Opening home dashboard")
|
||||
// TODO replace params = null by more explicit code
|
||||
openDashboard.invoke(
|
||||
scope = viewModelScope,
|
||||
params = null
|
||||
) { result ->
|
||||
result.either(
|
||||
fnL = { Timber.e(it, "Error while opening home dashboard") },
|
||||
fnR = { Timber.d("Home dashboard opened") }
|
||||
|
||||
viewModelScope.launch {
|
||||
openDashboard(params = null).either(
|
||||
fnR = { payload -> processEvents(payload.events) },
|
||||
fnL = { Timber.e(it, "Error while opening home dashboard") }
|
||||
)
|
||||
}
|
||||
}
|
||||
|
@ -241,7 +205,7 @@ class HomeDashboardViewModel(
|
|||
}
|
||||
|
||||
private fun navigateToPage(id: String) {
|
||||
closeDashboard.invoke(viewModelScope, CloseDashboard.Param.home()) { result ->
|
||||
closeDashboard(viewModelScope, CloseDashboard.Param.home()) { result ->
|
||||
result.either(
|
||||
fnL = { e -> Timber.e(e, "Error while closing a dashobard") },
|
||||
fnR = { navigation.postValue(EventWrapper(AppNavigation.Command.OpenPage(id))) }
|
||||
|
|
|
@ -19,7 +19,8 @@ class HomeDashboardViewModelFactory(
|
|||
private val createPage: CreatePage,
|
||||
private val getConfig: GetConfig,
|
||||
private val dnd: DragAndDrop,
|
||||
private val interceptEvents: InterceptEvents
|
||||
private val interceptEvents: InterceptEvents,
|
||||
private val eventConverter: HomeDashboardEventConverter
|
||||
) : ViewModelProvider.Factory {
|
||||
|
||||
@Suppress("UNCHECKED_CAST")
|
||||
|
@ -32,7 +33,8 @@ class HomeDashboardViewModelFactory(
|
|||
createPage = createPage,
|
||||
getConfig = getConfig,
|
||||
dragAndDrop = dnd,
|
||||
interceptEvents = interceptEvents
|
||||
interceptEvents = interceptEvents,
|
||||
eventConverter = eventConverter
|
||||
) as T
|
||||
}
|
||||
}
|
|
@ -5,7 +5,6 @@ import com.agileburo.anytype.core_ui.features.page.BlockView
|
|||
import com.agileburo.anytype.core_ui.model.UiBlock
|
||||
import com.agileburo.anytype.domain.block.model.Block
|
||||
import com.agileburo.anytype.domain.dashboard.model.HomeDashboard
|
||||
import com.agileburo.anytype.domain.emoji.Emojifier
|
||||
import com.agileburo.anytype.domain.misc.UrlBuilder
|
||||
import com.agileburo.anytype.presentation.desktop.DashboardView
|
||||
|
||||
|
@ -133,9 +132,7 @@ fun Block.Content.Text.marks(): List<Markup.Mark> = marks.mapNotNull { mark ->
|
|||
}
|
||||
}
|
||||
|
||||
suspend fun HomeDashboard.toView(
|
||||
emojifier: Emojifier
|
||||
): List<DashboardView.Document> = children.mapNotNull { id ->
|
||||
fun HomeDashboard.toView(): List<DashboardView.Document> = children.mapNotNull { id ->
|
||||
blocks.find { block -> block.id == id }?.let { model ->
|
||||
when (val content = model.content) {
|
||||
is Block.Content.Link -> {
|
||||
|
@ -146,7 +143,7 @@ suspend fun HomeDashboard.toView(
|
|||
title = details.details[content.target]?.name,
|
||||
emoji = details.details[content.target]?.icon?.let { name ->
|
||||
if (name.isNotEmpty())
|
||||
emojifier.fromShortName(name).unicode
|
||||
name
|
||||
else
|
||||
null
|
||||
}
|
||||
|
|
|
@ -0,0 +1,24 @@
|
|||
package com.agileburo.anytype.presentation.page
|
||||
|
||||
import com.agileburo.anytype.presentation.page.editor.Proxy
|
||||
import com.agileburo.anytype.presentation.page.editor.Store
|
||||
import com.agileburo.anytype.presentation.page.selection.SelectionStateHolder
|
||||
|
||||
interface Editor {
|
||||
|
||||
class Storage {
|
||||
val focus: Store<String> = Store.Focus()
|
||||
val details: Store.Details = Store.Details()
|
||||
}
|
||||
|
||||
class Proxer(
|
||||
val intents: Proxy.Intents = Proxy.Intents(),
|
||||
val changes: Proxy.Text.Changes = Proxy.Text.Changes(),
|
||||
val saves: Proxy.Text.Saves = Proxy.Text.Saves(),
|
||||
val payloads: Proxy.Payloads = Proxy.Payloads()
|
||||
)
|
||||
|
||||
class Memory(
|
||||
val selections: SelectionStateHolder
|
||||
)
|
||||
}
|
File diff suppressed because it is too large
Load diff
|
@ -2,19 +2,17 @@ package com.agileburo.anytype.presentation.page
|
|||
|
||||
import androidx.lifecycle.ViewModel
|
||||
import androidx.lifecycle.ViewModelProvider
|
||||
import com.agileburo.anytype.core_ui.features.page.pattern.Matcher
|
||||
import com.agileburo.anytype.core_ui.features.page.pattern.Pattern
|
||||
import com.agileburo.anytype.core_utils.tools.Counter
|
||||
import com.agileburo.anytype.domain.block.interactor.*
|
||||
import com.agileburo.anytype.domain.block.interactor.RemoveLinkMark
|
||||
import com.agileburo.anytype.domain.block.interactor.UpdateLinkMarks
|
||||
import com.agileburo.anytype.domain.block.interactor.UploadUrl
|
||||
import com.agileburo.anytype.domain.block.model.Block
|
||||
import com.agileburo.anytype.domain.download.DownloadFile
|
||||
import com.agileburo.anytype.domain.event.interactor.InterceptEvents
|
||||
import com.agileburo.anytype.domain.event.model.Event
|
||||
import com.agileburo.anytype.domain.misc.UrlBuilder
|
||||
import com.agileburo.anytype.domain.page.*
|
||||
import com.agileburo.anytype.presentation.common.StateReducer
|
||||
import com.agileburo.anytype.presentation.page.editor.Orchestrator
|
||||
import com.agileburo.anytype.presentation.page.render.DefaultBlockViewRenderer
|
||||
import com.agileburo.anytype.presentation.page.selection.SelectionStateHolder
|
||||
|
||||
open class PageViewModelFactory(
|
||||
private val openPage: OpenPage,
|
||||
|
@ -22,32 +20,14 @@ open class PageViewModelFactory(
|
|||
private val createPage: CreatePage,
|
||||
private val createDocument: CreateDocument,
|
||||
private val archiveDocument: ArchiveDocument,
|
||||
private val redo: Redo,
|
||||
private val undo: Undo,
|
||||
private val updateText: UpdateText,
|
||||
private val createBlock: CreateBlock,
|
||||
private val replaceBlock: ReplaceBlock,
|
||||
private val interceptEvents: InterceptEvents,
|
||||
private val updateCheckbox: UpdateCheckbox,
|
||||
private val unlinkBlocks: UnlinkBlocks,
|
||||
private val duplicateBlock: DuplicateBlock,
|
||||
private val updateTextStyle: UpdateTextStyle,
|
||||
private val updateTextColor: UpdateTextColor,
|
||||
private val updateBackgroundColor: UpdateBackgroundColor,
|
||||
private val updateLinkMarks: UpdateLinkMarks,
|
||||
private val removeLinkMark: RemoveLinkMark,
|
||||
private val mergeBlocks: MergeBlocks,
|
||||
private val uploadUrl: UploadUrl,
|
||||
private val splitBlock: SplitBlock,
|
||||
private val documentEventReducer: StateReducer<List<Block>, Event>,
|
||||
private val urlBuilder: UrlBuilder,
|
||||
private val downloadFile: DownloadFile,
|
||||
private val renderer: DefaultBlockViewRenderer,
|
||||
private val counter: Counter,
|
||||
private val patternMatcher: Matcher<Pattern>,
|
||||
private val updateTitle: UpdateTitle,
|
||||
private val selectionStateHolder: SelectionStateHolder,
|
||||
private val updateAlignment: UpdateBlockAlignment
|
||||
private val interactor: Orchestrator
|
||||
) : ViewModelProvider.Factory {
|
||||
|
||||
@Suppress("UNCHECKED_CAST")
|
||||
|
@ -55,35 +35,17 @@ open class PageViewModelFactory(
|
|||
return PageViewModel(
|
||||
openPage = openPage,
|
||||
closePage = closePage,
|
||||
undo = undo,
|
||||
redo = redo,
|
||||
updateText = updateText,
|
||||
createBlock = createBlock,
|
||||
archiveDocument = archiveDocument,
|
||||
interceptEvents = interceptEvents,
|
||||
updateCheckbox = updateCheckbox,
|
||||
duplicateBlock = duplicateBlock,
|
||||
unlinkBlocks = unlinkBlocks,
|
||||
updateTextStyle = updateTextStyle,
|
||||
updateTextColor = updateTextColor,
|
||||
updateBackgroundColor = updateBackgroundColor,
|
||||
updateLinkMarks = updateLinkMarks,
|
||||
removeLinkMark = removeLinkMark,
|
||||
mergeBlocks = mergeBlocks,
|
||||
splitBlock = splitBlock,
|
||||
uploadUrl = uploadUrl,
|
||||
createPage = createPage,
|
||||
documentExternalEventReducer = documentEventReducer,
|
||||
reducer = documentEventReducer,
|
||||
urlBuilder = urlBuilder,
|
||||
downloadFile = downloadFile,
|
||||
renderer = renderer,
|
||||
counter = counter,
|
||||
createDocument = createDocument,
|
||||
replaceBlock = replaceBlock,
|
||||
patternMatcher = patternMatcher,
|
||||
updateTitle = updateTitle,
|
||||
selectionStateHolder = selectionStateHolder,
|
||||
updateAlignment = updateAlignment
|
||||
orchestrator = interactor
|
||||
) as T
|
||||
}
|
||||
}
|
|
@ -0,0 +1,44 @@
|
|||
package com.agileburo.anytype.presentation.page.editor
|
||||
|
||||
import com.agileburo.anytype.core_ui.features.page.BlockView
|
||||
import com.agileburo.anytype.domain.common.Id
|
||||
import com.agileburo.anytype.domain.common.Url
|
||||
|
||||
sealed class Command {
|
||||
data class OpenPagePicker(
|
||||
val target: String
|
||||
) : Command()
|
||||
|
||||
data class OpenGallery(
|
||||
val mediaType: String
|
||||
) : Command()
|
||||
|
||||
data class OpenBookmarkSetter(
|
||||
val target: String,
|
||||
val context: String
|
||||
) : Command()
|
||||
|
||||
object OpenAddBlockPanel : Command()
|
||||
|
||||
data class OpenTurnIntoPanel(
|
||||
val target: Id
|
||||
) : Command()
|
||||
|
||||
object OpenMultiSelectTurnIntoPanel : Command()
|
||||
|
||||
data class RequestDownloadPermission(
|
||||
val id: String
|
||||
) : Command()
|
||||
|
||||
object PopBackStack : Command()
|
||||
|
||||
object CloseKeyboard : Command()
|
||||
|
||||
data class OpenActionBar(
|
||||
val block: BlockView
|
||||
) : Command()
|
||||
|
||||
data class Browse(
|
||||
val url: Url
|
||||
) : Command()
|
||||
}
|
|
@ -0,0 +1,5 @@
|
|||
package com.agileburo.anytype.presentation.page.editor
|
||||
|
||||
interface Converter<in INPUT, out OUTPUT> {
|
||||
fun convert(input: INPUT): OUTPUT
|
||||
}
|
|
@ -0,0 +1,114 @@
|
|||
package com.agileburo.anytype.presentation.page.editor
|
||||
|
||||
import com.agileburo.anytype.domain.block.model.Block
|
||||
import com.agileburo.anytype.domain.block.model.Position
|
||||
import com.agileburo.anytype.domain.common.Id
|
||||
|
||||
sealed class Intent {
|
||||
|
||||
sealed class Document : Intent() {
|
||||
|
||||
class Undo(
|
||||
val context: Id
|
||||
) : Document()
|
||||
|
||||
class Redo(
|
||||
val context: Id
|
||||
) : Document()
|
||||
|
||||
class UpdateTitle(
|
||||
val context: Id,
|
||||
val title: String
|
||||
) : Document()
|
||||
}
|
||||
|
||||
sealed class CRUD : Intent() {
|
||||
|
||||
class Replace(
|
||||
val context: Id,
|
||||
val target: Id,
|
||||
val prototype: Block.Prototype
|
||||
) : CRUD()
|
||||
|
||||
class Create(
|
||||
val context: Id,
|
||||
val target: Id,
|
||||
val position: Position,
|
||||
val prototype: Block.Prototype
|
||||
) : CRUD()
|
||||
|
||||
class Duplicate(
|
||||
val context: Id,
|
||||
val target: Id
|
||||
) : CRUD()
|
||||
|
||||
class Unlink(
|
||||
val context: Id,
|
||||
val targets: List<Id>,
|
||||
val previous: Id?,
|
||||
val next: Id?,
|
||||
val effects: List<SideEffect> = emptyList()
|
||||
) : CRUD()
|
||||
}
|
||||
|
||||
sealed class Text : Intent() {
|
||||
|
||||
class UpdateColor(
|
||||
val context: Id,
|
||||
val target: Id,
|
||||
val color: String
|
||||
) : Text()
|
||||
|
||||
class UpdateBackgroundColor(
|
||||
val context: Id,
|
||||
val targets: List<Id>,
|
||||
val color: String
|
||||
) : Text()
|
||||
|
||||
class Split(
|
||||
val context: Id,
|
||||
val target: Id,
|
||||
val index: Int
|
||||
) : Text()
|
||||
|
||||
class Merge(
|
||||
val context: Id,
|
||||
val previous: Id,
|
||||
val pair: Pair<Id, Id>
|
||||
) : Text()
|
||||
|
||||
class UpdateStyle(
|
||||
val context: Id,
|
||||
val targets: List<Id>,
|
||||
val style: Block.Content.Text.Style
|
||||
) : Text()
|
||||
|
||||
class UpdateCheckbox(
|
||||
val context: Id,
|
||||
val target: Id,
|
||||
val isChecked: Boolean
|
||||
) : Text()
|
||||
|
||||
class UpdateText(
|
||||
val context: Id,
|
||||
val target: Id,
|
||||
val text: String,
|
||||
val marks: List<Block.Content.Text.Mark>
|
||||
) : Text()
|
||||
|
||||
class Align(
|
||||
val context: Id,
|
||||
val target: Id,
|
||||
val alignment: Block.Align
|
||||
) : Text()
|
||||
}
|
||||
|
||||
sealed class Media : Intent() {
|
||||
|
||||
class DownloadFile(
|
||||
val url: String,
|
||||
val name: String
|
||||
) : Media()
|
||||
|
||||
}
|
||||
}
|
|
@ -0,0 +1,105 @@
|
|||
package com.agileburo.anytype.presentation.page.editor
|
||||
|
||||
import com.agileburo.anytype.core_ui.features.page.pattern.Matcher
|
||||
import com.agileburo.anytype.core_ui.features.page.pattern.Pattern
|
||||
import com.agileburo.anytype.domain.block.model.Block
|
||||
import com.agileburo.anytype.domain.common.Id
|
||||
import com.agileburo.anytype.presentation.page.Editor
|
||||
import com.agileburo.anytype.presentation.page.model.TextUpdate
|
||||
|
||||
interface Interactor {
|
||||
|
||||
class TextInteractor(
|
||||
private val proxies: Editor.Proxer,
|
||||
private val stores: Editor.Storage,
|
||||
private val matcher: Matcher<Pattern>
|
||||
) {
|
||||
|
||||
suspend fun consume(update: TextUpdate, context: Id) {
|
||||
if (update is TextUpdate.Default)
|
||||
proxies.saves.send(update)
|
||||
else if (update is TextUpdate.Pattern) {
|
||||
val patterns = matcher.match(update.text)
|
||||
when {
|
||||
patterns.isEmpty() -> proxies.saves.send(update)
|
||||
patterns.contains(Pattern.NUMBERED) -> replaceBy(
|
||||
context = context,
|
||||
target = update.target,
|
||||
prototype = Block.Prototype.Text(
|
||||
style = Block.Content.Text.Style.NUMBERED
|
||||
)
|
||||
)
|
||||
patterns.contains(Pattern.CHECKBOX) -> replaceBy(
|
||||
context = context,
|
||||
target = update.target,
|
||||
prototype = Block.Prototype.Text(
|
||||
style = Block.Content.Text.Style.CHECKBOX
|
||||
)
|
||||
)
|
||||
patterns.contains(Pattern.BULLET) -> replaceBy(
|
||||
context = context,
|
||||
target = update.target,
|
||||
prototype = Block.Prototype.Text(
|
||||
style = Block.Content.Text.Style.BULLET
|
||||
)
|
||||
)
|
||||
patterns.contains(Pattern.H1) -> replaceBy(
|
||||
context = context,
|
||||
target = update.target,
|
||||
prototype = Block.Prototype.Text(
|
||||
style = Block.Content.Text.Style.H1
|
||||
)
|
||||
)
|
||||
patterns.contains(Pattern.H2) -> replaceBy(
|
||||
context = context,
|
||||
target = update.target,
|
||||
prototype = Block.Prototype.Text(
|
||||
style = Block.Content.Text.Style.H2
|
||||
)
|
||||
)
|
||||
patterns.contains(Pattern.H3) -> replaceBy(
|
||||
context = context,
|
||||
target = update.target,
|
||||
prototype = Block.Prototype.Text(
|
||||
style = Block.Content.Text.Style.H3
|
||||
)
|
||||
)
|
||||
patterns.contains(Pattern.QUOTE) -> replaceBy(
|
||||
context = context,
|
||||
target = update.target,
|
||||
prototype = Block.Prototype.Text(
|
||||
style = Block.Content.Text.Style.QUOTE
|
||||
)
|
||||
)
|
||||
patterns.contains(Pattern.TOGGLE) -> replaceBy(
|
||||
context = context,
|
||||
target = update.target,
|
||||
prototype = Block.Prototype.Text(
|
||||
style = Block.Content.Text.Style.TOGGLE
|
||||
)
|
||||
)
|
||||
patterns.contains(Pattern.DIVIDER) -> replaceBy(
|
||||
context = context,
|
||||
target = update.target,
|
||||
prototype = Block.Prototype.Divider
|
||||
)
|
||||
else -> proxies.saves.send(update)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private suspend fun replaceBy(
|
||||
context: Id,
|
||||
target: Id,
|
||||
prototype: Block.Prototype
|
||||
) {
|
||||
proxies.intents.send(
|
||||
Intent.CRUD.Replace(
|
||||
context = context,
|
||||
target = target,
|
||||
prototype = prototype
|
||||
)
|
||||
)
|
||||
}
|
||||
}
|
||||
}
|
|
@ -0,0 +1,255 @@
|
|||
package com.agileburo.anytype.presentation.page.editor
|
||||
|
||||
import com.agileburo.anytype.domain.block.interactor.*
|
||||
import com.agileburo.anytype.domain.common.Id
|
||||
import com.agileburo.anytype.domain.download.DownloadFile
|
||||
import com.agileburo.anytype.domain.event.model.Payload
|
||||
import com.agileburo.anytype.domain.page.Redo
|
||||
import com.agileburo.anytype.domain.page.Undo
|
||||
import com.agileburo.anytype.domain.page.UpdateTitle
|
||||
import com.agileburo.anytype.presentation.page.Editor
|
||||
import kotlinx.coroutines.flow.collect
|
||||
import timber.log.Timber
|
||||
|
||||
class Orchestrator(
|
||||
private val createBlock: CreateBlock,
|
||||
private val replaceBlock: ReplaceBlock,
|
||||
private val updateTextColor: UpdateTextColor,
|
||||
private val updateBackgroundColor: UpdateBackgroundColor,
|
||||
private val duplicateBlock: DuplicateBlock,
|
||||
private val splitBlock: SplitBlock,
|
||||
private val mergeBlocks: MergeBlocks,
|
||||
private val unlinkBlocks: UnlinkBlocks,
|
||||
private val updateTextStyle: UpdateTextStyle,
|
||||
private val updateCheckbox: UpdateCheckbox,
|
||||
private val updateTitle: UpdateTitle,
|
||||
private val downloadFile: DownloadFile,
|
||||
private val updateText: UpdateText,
|
||||
private val updateAlignment: UpdateAlignment,
|
||||
private val undo: Undo,
|
||||
private val redo: Redo,
|
||||
val memory: Editor.Memory,
|
||||
val stores: Editor.Storage,
|
||||
val proxies: Editor.Proxer,
|
||||
val textInteractor: Interactor.TextInteractor
|
||||
) {
|
||||
|
||||
private val defaultOnSuccess: suspend (Pair<Id, Payload>) -> Unit = { (id, payload) ->
|
||||
stores.focus.update(id)
|
||||
proxies.payloads.send(payload)
|
||||
}
|
||||
|
||||
private val defaultOnError: suspend (Throwable) -> Unit = { Timber.e(it) }
|
||||
|
||||
suspend fun start() {
|
||||
proxies.intents.stream().collect { intent ->
|
||||
when (intent) {
|
||||
is Intent.CRUD.Create -> {
|
||||
createBlock(
|
||||
params = CreateBlock.Params(
|
||||
context = intent.context,
|
||||
target = intent.target,
|
||||
prototype = intent.prototype,
|
||||
position = intent.position
|
||||
)
|
||||
).proceed(
|
||||
failure = defaultOnError,
|
||||
success = defaultOnSuccess
|
||||
)
|
||||
}
|
||||
is Intent.CRUD.Replace -> {
|
||||
replaceBlock(
|
||||
params = ReplaceBlock.Params(
|
||||
context = intent.context,
|
||||
target = intent.target,
|
||||
prototype = intent.prototype
|
||||
)
|
||||
).proceed(
|
||||
failure = defaultOnError,
|
||||
success = defaultOnSuccess
|
||||
)
|
||||
}
|
||||
is Intent.CRUD.Duplicate -> {
|
||||
duplicateBlock(
|
||||
params = DuplicateBlock.Params(
|
||||
context = intent.context,
|
||||
original = intent.target
|
||||
)
|
||||
).proceed(
|
||||
failure = defaultOnError,
|
||||
success = defaultOnSuccess
|
||||
)
|
||||
}
|
||||
is Intent.CRUD.Unlink -> {
|
||||
unlinkBlocks(
|
||||
params = UnlinkBlocks.Params(
|
||||
context = intent.context,
|
||||
targets = intent.targets
|
||||
)
|
||||
).proceed(
|
||||
failure = defaultOnError,
|
||||
success = { payload ->
|
||||
val focus = intent.previous ?: intent.next
|
||||
if (focus != null) stores.focus.update(focus)
|
||||
processSideEffects(intent.effects)
|
||||
proxies.payloads.send(payload)
|
||||
}
|
||||
)
|
||||
}
|
||||
is Intent.Text.Split -> {
|
||||
splitBlock(
|
||||
params = SplitBlock.Params(
|
||||
context = intent.context,
|
||||
target = intent.target,
|
||||
index = intent.index
|
||||
)
|
||||
).proceed(
|
||||
failure = defaultOnError,
|
||||
success = { (id, payload) ->
|
||||
stores.focus.update(intent.target)
|
||||
proxies.payloads.send(payload)
|
||||
}
|
||||
)
|
||||
}
|
||||
is Intent.Text.Merge -> {
|
||||
mergeBlocks(
|
||||
params = MergeBlocks.Params(
|
||||
context = intent.context,
|
||||
pair = intent.pair
|
||||
)
|
||||
).proceed(
|
||||
failure = defaultOnError,
|
||||
success = { payload ->
|
||||
stores.focus.update(intent.previous)
|
||||
proxies.payloads.send(payload)
|
||||
}
|
||||
)
|
||||
}
|
||||
is Intent.Text.UpdateColor -> {
|
||||
updateTextColor(
|
||||
params = UpdateTextColor.Params(
|
||||
context = intent.context,
|
||||
target = intent.target,
|
||||
color = intent.color
|
||||
)
|
||||
).proceed(
|
||||
failure = defaultOnError,
|
||||
success = { payload -> proxies.payloads.send(payload) }
|
||||
)
|
||||
}
|
||||
is Intent.Text.UpdateBackgroundColor -> {
|
||||
updateBackgroundColor(
|
||||
params = UpdateBackgroundColor.Params(
|
||||
context = intent.context,
|
||||
targets = intent.targets,
|
||||
color = intent.color
|
||||
)
|
||||
).proceed(
|
||||
failure = defaultOnError,
|
||||
success = { payload -> proxies.payloads.send(payload) }
|
||||
)
|
||||
}
|
||||
is Intent.Text.UpdateStyle -> {
|
||||
updateTextStyle(
|
||||
params = UpdateTextStyle.Params(
|
||||
context = intent.context,
|
||||
targets = intent.targets,
|
||||
style = intent.style
|
||||
)
|
||||
).proceed(
|
||||
failure = defaultOnError,
|
||||
success = {}
|
||||
)
|
||||
}
|
||||
is Intent.Text.UpdateCheckbox -> {
|
||||
updateCheckbox(
|
||||
params = UpdateCheckbox.Params(
|
||||
context = intent.context,
|
||||
target = intent.target,
|
||||
isChecked = intent.isChecked
|
||||
)
|
||||
).proceed(
|
||||
failure = defaultOnError,
|
||||
success = {}
|
||||
)
|
||||
}
|
||||
is Intent.Text.UpdateText -> {
|
||||
updateText(
|
||||
params = UpdateText.Params(
|
||||
context = intent.context,
|
||||
target = intent.target,
|
||||
text = intent.text,
|
||||
marks = intent.marks
|
||||
)
|
||||
).proceed(
|
||||
failure = defaultOnError,
|
||||
success = {}
|
||||
)
|
||||
}
|
||||
is Intent.Text.Align -> {
|
||||
updateAlignment(
|
||||
params = UpdateAlignment.Params(
|
||||
context = intent.context,
|
||||
targets = listOf(intent.target),
|
||||
alignment = intent.alignment
|
||||
)
|
||||
).proceed(
|
||||
failure = defaultOnError,
|
||||
success = { payload ->
|
||||
proxies.payloads.send(payload)
|
||||
}
|
||||
)
|
||||
}
|
||||
is Intent.Document.Redo -> {
|
||||
redo(
|
||||
params = Redo.Params(
|
||||
context = intent.context
|
||||
)
|
||||
).proceed(
|
||||
failure = defaultOnError,
|
||||
success = { }
|
||||
)
|
||||
}
|
||||
is Intent.Document.Undo -> {
|
||||
undo(
|
||||
params = Undo.Params(
|
||||
context = intent.context
|
||||
)
|
||||
).proceed(
|
||||
failure = defaultOnError,
|
||||
success = {}
|
||||
)
|
||||
}
|
||||
is Intent.Document.UpdateTitle -> {
|
||||
updateTitle(
|
||||
params = UpdateTitle.Params(
|
||||
context = intent.context,
|
||||
title = intent.title
|
||||
)
|
||||
).proceed(
|
||||
failure = defaultOnError,
|
||||
success = {}
|
||||
)
|
||||
}
|
||||
is Intent.Media.DownloadFile -> {
|
||||
downloadFile(
|
||||
params = DownloadFile.Params(
|
||||
url = intent.url,
|
||||
name = intent.name
|
||||
)
|
||||
).proceed(
|
||||
failure = defaultOnError,
|
||||
success = {}
|
||||
)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private fun processSideEffects(effects: List<SideEffect>) {
|
||||
effects.forEach { effect ->
|
||||
if (effect is SideEffect.ClearMultiSelectSelection)
|
||||
memory.selections.clearSelections()
|
||||
}
|
||||
}
|
||||
}
|
|
@ -0,0 +1,41 @@
|
|||
package com.agileburo.anytype.presentation.page.editor
|
||||
|
||||
import com.agileburo.anytype.domain.event.model.Payload
|
||||
import com.agileburo.anytype.presentation.page.model.TextUpdate
|
||||
import kotlinx.coroutines.channels.Channel
|
||||
import kotlinx.coroutines.flow.Flow
|
||||
import kotlinx.coroutines.flow.consumeAsFlow
|
||||
|
||||
interface Proxy<T> {
|
||||
|
||||
/**
|
||||
* @return streams of values
|
||||
*/
|
||||
fun stream(): Flow<T>
|
||||
|
||||
/**
|
||||
* Updates current values
|
||||
*/
|
||||
suspend fun send(t: T)
|
||||
|
||||
fun cancel()
|
||||
|
||||
open class Subject<T> : Proxy<T> {
|
||||
|
||||
private val channel = Channel<T>()
|
||||
private val stream = channel.consumeAsFlow()
|
||||
|
||||
override fun stream(): Flow<T> = stream
|
||||
override suspend fun send(t: T) = channel.send(t)
|
||||
override fun cancel() = channel.cancel()
|
||||
}
|
||||
|
||||
sealed class Text : Subject<TextUpdate>() {
|
||||
class Changes : Text()
|
||||
class Saves : Text()
|
||||
}
|
||||
|
||||
class Intents : Subject<Intent>()
|
||||
|
||||
class Payloads : Subject<Payload>()
|
||||
}
|
|
@ -0,0 +1,5 @@
|
|||
package com.agileburo.anytype.presentation.page.editor
|
||||
|
||||
sealed class SideEffect {
|
||||
object ClearMultiSelectSelection : SideEffect()
|
||||
}
|
|
@ -0,0 +1,52 @@
|
|||
package com.agileburo.anytype.presentation.page.editor
|
||||
|
||||
import com.agileburo.anytype.domain.block.model.Block
|
||||
import com.agileburo.anytype.domain.common.Id
|
||||
import com.agileburo.anytype.presentation.page.PageViewModel
|
||||
import kotlinx.coroutines.channels.ConflatedBroadcastChannel
|
||||
import kotlinx.coroutines.flow.Flow
|
||||
import kotlinx.coroutines.flow.asFlow
|
||||
|
||||
/**
|
||||
* Reactive store
|
||||
* @param T stored type
|
||||
*/
|
||||
interface Store<T> {
|
||||
|
||||
/**
|
||||
* @return streams of values
|
||||
*/
|
||||
fun stream(): Flow<T>
|
||||
|
||||
/**
|
||||
* @return current/last value
|
||||
*/
|
||||
fun current(): T
|
||||
|
||||
/**
|
||||
* Updates current values
|
||||
*/
|
||||
suspend fun update(t: T)
|
||||
|
||||
fun cancel()
|
||||
|
||||
open class Conflated<T>(default: T) : Store<T> {
|
||||
|
||||
private val channel = ConflatedBroadcastChannel(default)
|
||||
private val stream = channel.asFlow()
|
||||
|
||||
override fun stream(): Flow<T> = stream
|
||||
override fun current(): T = channel.value
|
||||
override suspend fun update(t: T) = channel.send(t)
|
||||
override fun cancel() = channel.cancel()
|
||||
}
|
||||
|
||||
class Focus : Conflated<String>(PageViewModel.EMPTY_FOCUS_ID)
|
||||
class Context : Conflated<String>("")
|
||||
|
||||
class Details : Conflated<Block.Details>(Block.Details()) {
|
||||
suspend fun add(target: Id, fields: Block.Fields) {
|
||||
update(current().copy(details = current().details + mapOf(target to fields)))
|
||||
}
|
||||
}
|
||||
}
|
|
@ -0,0 +1,114 @@
|
|||
package com.agileburo.anytype.presentation.page.editor
|
||||
|
||||
import com.agileburo.anytype.core_ui.common.Markup
|
||||
import com.agileburo.anytype.domain.block.model.Block
|
||||
import com.agileburo.anytype.domain.common.Id
|
||||
import com.agileburo.anytype.domain.ext.addMark
|
||||
import com.agileburo.anytype.domain.ext.content
|
||||
import com.agileburo.anytype.domain.misc.Reducer
|
||||
import com.agileburo.anytype.presentation.page.model.TextUpdate
|
||||
|
||||
sealed class Transformation {
|
||||
|
||||
data class ApplyMarkup(
|
||||
val target: Id,
|
||||
val type: Markup.Type,
|
||||
val range: IntRange,
|
||||
val param: String?
|
||||
) : Reducer<List<Block>, ApplyMarkup> {
|
||||
|
||||
override fun reduce(state: List<Block>, event: ApplyMarkup): List<Block> {
|
||||
|
||||
val target = state.first { it.id == target }
|
||||
val content = target.content<Block.Content.Text>()
|
||||
|
||||
val mark = Block.Content.Text.Mark(
|
||||
range = range,
|
||||
type = when (type) {
|
||||
Markup.Type.BOLD -> Block.Content.Text.Mark.Type.BOLD
|
||||
Markup.Type.ITALIC -> Block.Content.Text.Mark.Type.ITALIC
|
||||
Markup.Type.STRIKETHROUGH -> Block.Content.Text.Mark.Type.STRIKETHROUGH
|
||||
Markup.Type.TEXT_COLOR -> Block.Content.Text.Mark.Type.TEXT_COLOR
|
||||
Markup.Type.LINK -> Block.Content.Text.Mark.Type.LINK
|
||||
Markup.Type.BACKGROUND_COLOR -> Block.Content.Text.Mark.Type.BACKGROUND_COLOR
|
||||
Markup.Type.KEYBOARD -> Block.Content.Text.Mark.Type.KEYBOARD
|
||||
},
|
||||
param = param
|
||||
)
|
||||
|
||||
val marks = content.marks.addMark(mark)
|
||||
|
||||
val new = target.copy(
|
||||
content = content.copy(marks = marks)
|
||||
)
|
||||
|
||||
return state.map { block ->
|
||||
if (block.id != event.target)
|
||||
block
|
||||
else
|
||||
new
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
data class UpdateText(
|
||||
val update: TextUpdate
|
||||
) : Reducer<List<Block>, UpdateText> {
|
||||
|
||||
override fun reduce(
|
||||
state: List<Block>,
|
||||
event: UpdateText
|
||||
): List<Block> = state.map { block ->
|
||||
if (block.id == update.target) {
|
||||
block.copy(
|
||||
content = block.content<Block.Content.Text>().copy(
|
||||
text = update.text,
|
||||
marks = update.markup.filter {
|
||||
it.range.first != it.range.last
|
||||
}
|
||||
)
|
||||
)
|
||||
} else
|
||||
block
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
fun Block.updateText(update: TextUpdate): Block {
|
||||
return copy(
|
||||
content = content<Block.Content.Text>().copy(
|
||||
text = update.text,
|
||||
marks = update.markup.filter {
|
||||
it.range.first != it.range.last
|
||||
}
|
||||
)
|
||||
)
|
||||
}
|
||||
|
||||
fun Block.markup(
|
||||
type: Markup.Type,
|
||||
range: IntRange,
|
||||
param: String?
|
||||
): Block {
|
||||
|
||||
val content = content<Block.Content.Text>()
|
||||
|
||||
val mark = Block.Content.Text.Mark(
|
||||
range = range,
|
||||
type = when (type) {
|
||||
Markup.Type.BOLD -> Block.Content.Text.Mark.Type.BOLD
|
||||
Markup.Type.ITALIC -> Block.Content.Text.Mark.Type.ITALIC
|
||||
Markup.Type.STRIKETHROUGH -> Block.Content.Text.Mark.Type.STRIKETHROUGH
|
||||
Markup.Type.TEXT_COLOR -> Block.Content.Text.Mark.Type.TEXT_COLOR
|
||||
Markup.Type.LINK -> Block.Content.Text.Mark.Type.LINK
|
||||
Markup.Type.BACKGROUND_COLOR -> Block.Content.Text.Mark.Type.BACKGROUND_COLOR
|
||||
Markup.Type.KEYBOARD -> Block.Content.Text.Mark.Type.KEYBOARD
|
||||
},
|
||||
param = param
|
||||
)
|
||||
|
||||
val marks = content.marks.addMark(mark)
|
||||
|
||||
return copy(content = content.copy(marks = marks))
|
||||
}
|
|
@ -0,0 +1,15 @@
|
|||
package com.agileburo.anytype.presentation.page.editor
|
||||
|
||||
import com.agileburo.anytype.core_ui.features.page.BlockView
|
||||
import com.agileburo.anytype.domain.block.model.Block
|
||||
|
||||
sealed class ViewState {
|
||||
object Loading : ViewState()
|
||||
data class Success(val blocks: List<BlockView>) : ViewState()
|
||||
data class Error(val message: String) : ViewState()
|
||||
data class OpenLinkScreen(
|
||||
val pageId: String,
|
||||
val block: Block,
|
||||
val range: IntRange
|
||||
) : ViewState()
|
||||
}
|
|
@ -1,6 +1,5 @@
|
|||
package com.agileburo.anytype.presentation.page.model
|
||||
|
||||
import com.agileburo.anytype.core_ui.features.page.pattern.Pattern
|
||||
import com.agileburo.anytype.domain.block.model.Block
|
||||
import com.agileburo.anytype.domain.common.Id
|
||||
|
||||
|
@ -9,11 +8,34 @@ import com.agileburo.anytype.domain.common.Id
|
|||
* @property target id of the text block, in which this change occurs
|
||||
* @property text new text for this [target]
|
||||
* @property markup markup, associated with this [text]
|
||||
* @property patterns editor patterns found in this [text]
|
||||
*/
|
||||
class TextUpdate(
|
||||
val target: Id,
|
||||
val text: String,
|
||||
val markup: List<Block.Content.Text.Mark>,
|
||||
val patterns: List<Pattern>
|
||||
)
|
||||
sealed class TextUpdate {
|
||||
|
||||
abstract val target: Id
|
||||
abstract val text: String
|
||||
abstract val markup: List<Block.Content.Text.Mark>
|
||||
|
||||
/**
|
||||
* Default text update.
|
||||
* @property target id of the text block, in which this change occurs
|
||||
* @property text new text for this [target]
|
||||
* @property markup markup, associated with this [text]
|
||||
*/
|
||||
data class Default(
|
||||
override val target: Id,
|
||||
override val text: String,
|
||||
override val markup: List<Block.Content.Text.Mark>
|
||||
) : TextUpdate()
|
||||
|
||||
/**
|
||||
* Text update qui may contain patterns we need to detect.
|
||||
* @property target id of the text block, in which this change occurs
|
||||
* @property text new text for this [target]
|
||||
* @property markup markup, associated with this [text]
|
||||
*/
|
||||
data class Pattern(
|
||||
override val target: Id,
|
||||
override val text: String,
|
||||
override val markup: List<Block.Content.Text.Mark>
|
||||
) : TextUpdate()
|
||||
}
|
|
@ -111,7 +111,7 @@ class PageIconPickerViewModel(
|
|||
setIconName.run(
|
||||
params = SetIconName.Params(
|
||||
target = action.target,
|
||||
name = ":${action.alias}:",
|
||||
name = action.unicode,
|
||||
context = action.context
|
||||
)
|
||||
)
|
||||
|
|
|
@ -1,7 +1,6 @@
|
|||
package com.agileburo.anytype.presentation.page.render
|
||||
|
||||
import com.agileburo.anytype.core_ui.features.page.BlockView
|
||||
import com.agileburo.anytype.core_utils.tools.Counter
|
||||
import com.agileburo.anytype.domain.block.model.Block
|
||||
import com.agileburo.anytype.domain.common.Id
|
||||
import com.agileburo.anytype.domain.page.EditorMode
|
||||
|
@ -24,7 +23,6 @@ interface BlockViewRenderer {
|
|||
focus: Id,
|
||||
anchor: Id,
|
||||
indent: Int,
|
||||
counter: Counter,
|
||||
details: Block.Details = Block.Details(emptyMap())
|
||||
): List<BlockView>
|
||||
}
|
|
@ -12,8 +12,8 @@ import com.agileburo.anytype.presentation.mapper.*
|
|||
import com.agileburo.anytype.presentation.page.toggle.ToggleStateHolder
|
||||
|
||||
class DefaultBlockViewRenderer(
|
||||
private val counter: Counter,
|
||||
private val urlBuilder: UrlBuilder,
|
||||
private val emojifier: Emojifier,
|
||||
private val toggleStateHolder: ToggleStateHolder
|
||||
) : BlockViewRenderer, ToggleStateHolder by toggleStateHolder {
|
||||
|
||||
|
@ -23,7 +23,6 @@ class DefaultBlockViewRenderer(
|
|||
focus: Id,
|
||||
anchor: Id,
|
||||
indent: Int,
|
||||
counter: Counter,
|
||||
details: Block.Details
|
||||
): List<BlockView> {
|
||||
|
||||
|
@ -87,7 +86,6 @@ class DefaultBlockViewRenderer(
|
|||
indent = indent.inc(),
|
||||
anchor = block.id,
|
||||
root = root,
|
||||
counter = counter,
|
||||
details = details
|
||||
)
|
||||
)
|
||||
|
@ -139,13 +137,26 @@ class DefaultBlockViewRenderer(
|
|||
counter.reset()
|
||||
result.add(file(content, block, indent))
|
||||
}
|
||||
is Content.Layout -> {
|
||||
counter.reset()
|
||||
result.addAll(
|
||||
render(
|
||||
mode = mode,
|
||||
focus = focus,
|
||||
indent = indent,
|
||||
anchor = block.id,
|
||||
root = root,
|
||||
details = details
|
||||
)
|
||||
)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return result
|
||||
}
|
||||
|
||||
private suspend fun buildTitle(
|
||||
private fun buildTitle(
|
||||
mode: EditorMode,
|
||||
anchor: Id,
|
||||
root: Block,
|
||||
|
@ -162,7 +173,7 @@ class DefaultBlockViewRenderer(
|
|||
text = details.details[root.id]?.name,
|
||||
emoji = details.details[root.id]?.icon?.let { name ->
|
||||
if (name.isNotEmpty())
|
||||
emojifier.fromShortName(name).unicode
|
||||
name
|
||||
else
|
||||
null
|
||||
}
|
||||
|
@ -384,7 +395,7 @@ class DefaultBlockViewRenderer(
|
|||
else -> throw IllegalStateException("Unexpected file type: ${content.type}")
|
||||
}
|
||||
|
||||
private suspend fun title(
|
||||
private fun title(
|
||||
mode: EditorMode,
|
||||
block: Block,
|
||||
content: Content.Text,
|
||||
|
@ -396,14 +407,14 @@ class DefaultBlockViewRenderer(
|
|||
text = content.text,
|
||||
emoji = root.fields.icon?.let { name ->
|
||||
if (name.isNotEmpty())
|
||||
emojifier.fromShortName(name).unicode
|
||||
name
|
||||
else
|
||||
null
|
||||
},
|
||||
focused = block.id == focus
|
||||
)
|
||||
|
||||
private suspend fun page(
|
||||
private fun page(
|
||||
block: Block,
|
||||
content: Content.Link,
|
||||
indent: Int,
|
||||
|
@ -413,7 +424,7 @@ class DefaultBlockViewRenderer(
|
|||
isEmpty = true,
|
||||
emoji = details.details[content.target]?.icon?.let { name ->
|
||||
if (name.isNotEmpty())
|
||||
emojifier.fromShortName(name).unicode
|
||||
name
|
||||
else
|
||||
null
|
||||
},
|
||||
|
|
|
@ -46,13 +46,11 @@ class HomeDashboardViewMapperTest {
|
|||
blocks = listOf(child),
|
||||
children = listOf(child.id),
|
||||
fields = Block.Fields.empty(),
|
||||
type = Block.Content.Dashboard.Type.MAIN_SCREEN
|
||||
type = Block.Content.Smart.Type.HOME
|
||||
)
|
||||
|
||||
val view = runBlocking {
|
||||
dashboard.toView(
|
||||
emojifier = emojifier
|
||||
)
|
||||
dashboard.toView()
|
||||
}
|
||||
|
||||
assertEquals(
|
||||
|
@ -85,14 +83,14 @@ class HomeDashboardViewMapperTest {
|
|||
blocks = listOf(child),
|
||||
children = listOf(child.id),
|
||||
fields = Block.Fields.empty(),
|
||||
type = Block.Content.Dashboard.Type.MAIN_SCREEN
|
||||
type = Block.Content.Smart.Type.HOME
|
||||
)
|
||||
|
||||
emojifier.stub {
|
||||
onBlocking { fromShortName(any()) } doReturn emoji
|
||||
}
|
||||
|
||||
val view: List<DashboardView> = runBlocking { dashboard.toView(emojifier = emojifier) }
|
||||
val view: List<DashboardView> = runBlocking { dashboard.toView() }
|
||||
|
||||
assertEquals(
|
||||
expected = listOf(
|
||||
|
|
|
@ -20,8 +20,10 @@ import com.agileburo.anytype.domain.emoji.Emoji
|
|||
import com.agileburo.anytype.domain.emoji.Emojifier
|
||||
import com.agileburo.anytype.domain.event.interactor.InterceptEvents
|
||||
import com.agileburo.anytype.domain.event.model.Event
|
||||
import com.agileburo.anytype.domain.event.model.Payload
|
||||
import com.agileburo.anytype.domain.image.LoadImage
|
||||
import com.agileburo.anytype.domain.page.CreatePage
|
||||
import com.agileburo.anytype.presentation.desktop.HomeDashboardEventConverter
|
||||
import com.agileburo.anytype.presentation.desktop.HomeDashboardStateMachine
|
||||
import com.agileburo.anytype.presentation.desktop.HomeDashboardViewModel
|
||||
import com.agileburo.anytype.presentation.mapper.toView
|
||||
|
@ -35,6 +37,7 @@ import kotlinx.coroutines.flow.Flow
|
|||
import kotlinx.coroutines.flow.flow
|
||||
import kotlinx.coroutines.flow.flowOf
|
||||
import kotlinx.coroutines.runBlocking
|
||||
import kotlinx.coroutines.test.runBlockingTest
|
||||
import org.junit.Before
|
||||
import org.junit.Rule
|
||||
import org.junit.Test
|
||||
|
@ -74,9 +77,6 @@ class HomeDashboardViewModelTest {
|
|||
@Mock
|
||||
lateinit var dnd: DragAndDrop
|
||||
|
||||
@Mock
|
||||
lateinit var emojifier: Emojifier
|
||||
|
||||
private lateinit var vm: HomeDashboardViewModel
|
||||
|
||||
@Before
|
||||
|
@ -93,20 +93,28 @@ class HomeDashboardViewModelTest {
|
|||
createPage = createPage,
|
||||
getConfig = getConfig,
|
||||
dragAndDrop = dnd,
|
||||
interceptEvents = interceptEvents
|
||||
interceptEvents = interceptEvents,
|
||||
eventConverter = HomeDashboardEventConverter.DefaultConverter()
|
||||
)
|
||||
}
|
||||
|
||||
@Test
|
||||
fun `should only start getting config when view model is initialized`() {
|
||||
|
||||
val config =
|
||||
Config(home = MockDataFactory.randomUuid(), gateway = MockDataFactory.randomUuid())
|
||||
// SETUP
|
||||
|
||||
val config = Config(
|
||||
home = MockDataFactory.randomUuid(),
|
||||
gateway = MockDataFactory.randomUuid()
|
||||
)
|
||||
|
||||
val response = Either.Right(config)
|
||||
|
||||
stubGetConfig(response)
|
||||
stubObserveEvents(params = InterceptEvents.Params(context = null))
|
||||
|
||||
// TESTING
|
||||
|
||||
vm = buildViewModel()
|
||||
|
||||
verify(getConfig, times(1)).invoke(any(), any(), any())
|
||||
|
@ -118,15 +126,22 @@ class HomeDashboardViewModelTest {
|
|||
@Test
|
||||
fun `should start observing events after receiving config`() {
|
||||
|
||||
val config =
|
||||
Config(home = MockDataFactory.randomUuid(), gateway = MockDataFactory.randomUuid())
|
||||
// SETUP
|
||||
|
||||
val config = Config(
|
||||
home = MockDataFactory.randomUuid(),
|
||||
gateway = MockDataFactory.randomUuid()
|
||||
)
|
||||
|
||||
val response = Either.Right(config)
|
||||
|
||||
val params = InterceptEvents.Params(context = null)
|
||||
val params = InterceptEvents.Params(context = config.home)
|
||||
|
||||
stubGetConfig(response)
|
||||
stubObserveEvents(params = params)
|
||||
|
||||
// TESTING
|
||||
|
||||
vm = buildViewModel()
|
||||
|
||||
verify(getConfig, times(1)).invoke(any(), any(), any())
|
||||
|
@ -136,12 +151,19 @@ class HomeDashboardViewModelTest {
|
|||
@Test
|
||||
fun `should start observing home dashboard after receiving config`() {
|
||||
|
||||
val config =
|
||||
Config(home = MockDataFactory.randomUuid(), gateway = MockDataFactory.randomUuid())
|
||||
// SETUP
|
||||
|
||||
val config = Config(
|
||||
home = MockDataFactory.randomUuid(),
|
||||
gateway = MockDataFactory.randomUuid()
|
||||
)
|
||||
|
||||
val response = Either.Right(config)
|
||||
|
||||
stubGetConfig(response)
|
||||
stubObserveEvents(params = InterceptEvents.Params(context = null))
|
||||
stubObserveEvents(params = InterceptEvents.Params(context = config.home))
|
||||
|
||||
// TESTING
|
||||
|
||||
vm = buildViewModel()
|
||||
|
||||
|
@ -154,11 +176,18 @@ class HomeDashboardViewModelTest {
|
|||
@Test
|
||||
fun `should emit loading state when home dashboard loading started`() {
|
||||
|
||||
val config =
|
||||
Config(home = MockDataFactory.randomUuid(), gateway = MockDataFactory.randomUuid())
|
||||
// SETUP
|
||||
|
||||
val config = Config(
|
||||
home = MockDataFactory.randomUuid(),
|
||||
gateway = MockDataFactory.randomUuid()
|
||||
)
|
||||
|
||||
stubGetConfig(Either.Right(config))
|
||||
stubObserveEvents(params = InterceptEvents.Params(context = null))
|
||||
stubObserveEvents(params = InterceptEvents.Params(context = config.home))
|
||||
stubOpenDashboard()
|
||||
|
||||
// TESTING
|
||||
|
||||
vm = buildViewModel()
|
||||
|
||||
|
@ -177,8 +206,12 @@ class HomeDashboardViewModelTest {
|
|||
@Test
|
||||
fun `should emit view state with dashboard when home dashboard loading started`() {
|
||||
|
||||
val config =
|
||||
Config(home = MockDataFactory.randomUuid(), gateway = MockDataFactory.randomUuid())
|
||||
// SETUP
|
||||
|
||||
val config = Config(
|
||||
home = MockDataFactory.randomUuid(),
|
||||
gateway = MockDataFactory.randomUuid()
|
||||
)
|
||||
|
||||
val page = Block(
|
||||
id = MockDataFactory.randomUuid(),
|
||||
|
@ -191,19 +224,21 @@ class HomeDashboardViewModelTest {
|
|||
|
||||
val dashboard = Block(
|
||||
id = config.home,
|
||||
content = Block.Content.Dashboard(
|
||||
type = Block.Content.Dashboard.Type.MAIN_SCREEN
|
||||
content = Block.Content.Smart(
|
||||
type = Block.Content.Smart.Type.HOME
|
||||
),
|
||||
children = listOf(page.id),
|
||||
fields = Block.Fields(map = mapOf("name" to MockDataFactory.randomString()))
|
||||
)
|
||||
|
||||
val delayInMillis = 100L
|
||||
stubGetConfig(Either.Right(config))
|
||||
|
||||
val events = flow {
|
||||
delay(delayInMillis)
|
||||
emit(
|
||||
listOf(
|
||||
stubObserveEvents(params = InterceptEvents.Params(context = config.home))
|
||||
|
||||
stubOpenDashboard(
|
||||
payload = Payload(
|
||||
context = config.home,
|
||||
events = listOf(
|
||||
Event.Command.ShowBlock(
|
||||
root = config.home,
|
||||
context = config.home,
|
||||
|
@ -211,30 +246,14 @@ class HomeDashboardViewModelTest {
|
|||
)
|
||||
)
|
||||
)
|
||||
}
|
||||
|
||||
stubGetConfig(Either.Right(config))
|
||||
stubObserveEvents(
|
||||
params = InterceptEvents.Params(context = null),
|
||||
flow = events
|
||||
)
|
||||
stubOpenDashboard()
|
||||
|
||||
// TESTING
|
||||
|
||||
vm = buildViewModel()
|
||||
|
||||
vm.onViewCreated()
|
||||
|
||||
vm.state.test().assertValue(
|
||||
HomeDashboardStateMachine.State(
|
||||
isLoading = true,
|
||||
isInitialzed = true,
|
||||
dashboard = null,
|
||||
error = null
|
||||
)
|
||||
)
|
||||
|
||||
coroutineTestRule.advanceTime(delayInMillis)
|
||||
|
||||
vm.state.test().assertValue(
|
||||
HomeDashboardStateMachine.State(
|
||||
isLoading = false,
|
||||
|
@ -248,6 +267,8 @@ class HomeDashboardViewModelTest {
|
|||
@Test
|
||||
fun `block dragging events do not alter overall state`() {
|
||||
|
||||
// SETUP
|
||||
|
||||
val config = Config(
|
||||
home = MockDataFactory.randomUuid(),
|
||||
gateway = MockDataFactory.randomUuid()
|
||||
|
@ -293,11 +314,10 @@ class HomeDashboardViewModelTest {
|
|||
|
||||
val dashboard = Block(
|
||||
id = config.home,
|
||||
content = Block.Content.Dashboard(
|
||||
type = Block.Content.Dashboard.Type.MAIN_SCREEN
|
||||
content = Block.Content.Smart(
|
||||
type = Block.Content.Smart.Type.HOME
|
||||
),
|
||||
children = pages.map { page -> page.id },
|
||||
|
||||
fields = Block.Fields.empty()
|
||||
)
|
||||
|
||||
|
@ -316,16 +336,23 @@ class HomeDashboardViewModelTest {
|
|||
)
|
||||
}
|
||||
|
||||
emojifier.stub {
|
||||
onBlocking { fromShortName(any()) } doReturn emoji
|
||||
}
|
||||
stubGetConfig(
|
||||
Either.Right(config)
|
||||
)
|
||||
|
||||
stubGetConfig(Either.Right(config))
|
||||
stubObserveEvents(
|
||||
params = InterceptEvents.Params(context = null),
|
||||
params = InterceptEvents.Params(context = config.home),
|
||||
flow = events
|
||||
)
|
||||
stubOpenDashboard()
|
||||
|
||||
stubOpenDashboard(
|
||||
payload = Payload(
|
||||
context = config.home,
|
||||
events = emptyList()
|
||||
)
|
||||
)
|
||||
|
||||
// TESTING
|
||||
|
||||
vm = buildViewModel()
|
||||
|
||||
|
@ -349,9 +376,7 @@ class HomeDashboardViewModelTest {
|
|||
dashboard,
|
||||
pages.first(),
|
||||
pages.last()
|
||||
).toHomeDashboard(dashboard.id).toView(
|
||||
emojifier = emojifier
|
||||
)
|
||||
).toHomeDashboard(dashboard.id).toView()
|
||||
}
|
||||
|
||||
val from = 0
|
||||
|
@ -418,24 +443,15 @@ class HomeDashboardViewModelTest {
|
|||
val dashboard = HomeDashboard(
|
||||
id = config.home,
|
||||
fields = Block.Fields(map = mapOf("name" to MockDataFactory.randomString())),
|
||||
type = Block.Content.Dashboard.Type.MAIN_SCREEN,
|
||||
type = Block.Content.Smart.Type.HOME,
|
||||
blocks = pages,
|
||||
children = pages.map { it.id }
|
||||
)
|
||||
|
||||
val delayInMillis = 100L
|
||||
|
||||
val flow = flow {
|
||||
delay(delayInMillis)
|
||||
emit(dashboard)
|
||||
}
|
||||
|
||||
emojifier.stub {
|
||||
onBlocking { fromShortName(any()) } doReturn emoji
|
||||
}
|
||||
|
||||
stubGetConfig(Either.Right(config))
|
||||
stubObserveEvents(params = InterceptEvents.Params(context = null))
|
||||
stubObserveEvents(params = InterceptEvents.Params(context = config.home))
|
||||
stubOpenDashboard()
|
||||
|
||||
vm = buildViewModel()
|
||||
|
@ -445,9 +461,7 @@ class HomeDashboardViewModelTest {
|
|||
coroutineTestRule.advanceTime(delayInMillis)
|
||||
|
||||
val views = runBlocking {
|
||||
dashboard.toView(
|
||||
emojifier = emojifier
|
||||
)
|
||||
dashboard.toView()
|
||||
}
|
||||
|
||||
val from = 0
|
||||
|
@ -479,16 +493,27 @@ class HomeDashboardViewModelTest {
|
|||
@Test
|
||||
fun `should proceed with getting account and opening dashboard when view is created`() {
|
||||
|
||||
val config =
|
||||
Config(home = MockDataFactory.randomUuid(), gateway = MockDataFactory.randomUuid())
|
||||
// SETUP
|
||||
|
||||
val config = Config(
|
||||
home = MockDataFactory.randomUuid(),
|
||||
gateway = MockDataFactory.randomUuid()
|
||||
)
|
||||
|
||||
stubGetConfig(Either.Right(config))
|
||||
stubObserveEvents(params = InterceptEvents.Params(context = null))
|
||||
stubObserveEvents(params = InterceptEvents.Params(context = config.home))
|
||||
stubOpenDashboard()
|
||||
|
||||
// TESTING
|
||||
|
||||
vm = buildViewModel()
|
||||
vm.onViewCreated()
|
||||
|
||||
verify(getCurrentAccount, times(1)).invoke(any(), any(), any())
|
||||
verify(openDashboard, times(1)).invoke(any(), eq(null), any())
|
||||
|
||||
runBlockingTest {
|
||||
verify(openDashboard, times(1)).invoke(eq(null))
|
||||
}
|
||||
}
|
||||
|
||||
@Test
|
||||
|
@ -504,6 +529,8 @@ class HomeDashboardViewModelTest {
|
|||
val response = Either.Right(account)
|
||||
|
||||
stubGetCurrentAccount(response)
|
||||
stubObserveEvents()
|
||||
stubOpenDashboard()
|
||||
|
||||
vm = buildViewModel()
|
||||
|
||||
|
@ -533,8 +560,8 @@ class HomeDashboardViewModelTest {
|
|||
val imageResponse = Either.Right(blob)
|
||||
|
||||
stubObserveEvents()
|
||||
|
||||
stubGetCurrentAccount(accountResponse)
|
||||
stubOpenDashboard()
|
||||
|
||||
loadImage.stub {
|
||||
onBlocking { invoke(any(), any(), any()) } doAnswer { answer ->
|
||||
|
@ -568,6 +595,7 @@ class HomeDashboardViewModelTest {
|
|||
|
||||
stubObserveEvents()
|
||||
stubGetCurrentAccount(accountResponse)
|
||||
stubOpenDashboard()
|
||||
|
||||
vm = buildViewModel()
|
||||
|
||||
|
@ -595,18 +623,8 @@ class HomeDashboardViewModelTest {
|
|||
val id = MockDataFactory.randomUuid()
|
||||
|
||||
stubObserveEvents()
|
||||
|
||||
closeDashboard.stub {
|
||||
onBlocking { invoke(any(), any(), any()) } doAnswer { answer ->
|
||||
answer.getArgument<(Either<Throwable, Unit>) -> Unit>(2)(Either.Right(Unit))
|
||||
}
|
||||
}
|
||||
|
||||
createPage.stub {
|
||||
onBlocking { invoke(any(), any(), any()) } doAnswer { answer ->
|
||||
answer.getArgument<(Either<Throwable, String>) -> Unit>(2)(Either.Right(id))
|
||||
}
|
||||
}
|
||||
stubCloseDashboard()
|
||||
stubCreatePage(id)
|
||||
|
||||
vm = buildViewModel()
|
||||
|
||||
|
@ -647,8 +665,8 @@ class HomeDashboardViewModelTest {
|
|||
|
||||
val dashboard = Block(
|
||||
id = config.home,
|
||||
content = Block.Content.Dashboard(
|
||||
type = Block.Content.Dashboard.Type.MAIN_SCREEN
|
||||
content = Block.Content.Smart(
|
||||
type = Block.Content.Smart.Type.HOME
|
||||
),
|
||||
children = listOf(page.id),
|
||||
fields = Block.Fields(map = mapOf("name" to dashboardName))
|
||||
|
@ -676,10 +694,12 @@ class HomeDashboardViewModelTest {
|
|||
}
|
||||
|
||||
stubGetConfig(Either.Right(config))
|
||||
|
||||
stubObserveEvents(
|
||||
flow = events,
|
||||
params = InterceptEvents.Params(context = null)
|
||||
params = InterceptEvents.Params(context = config.home)
|
||||
)
|
||||
|
||||
stubOpenDashboard()
|
||||
|
||||
vm = buildViewModel()
|
||||
|
@ -691,7 +711,7 @@ class HomeDashboardViewModelTest {
|
|||
val firstExpectedState = HomeDashboard(
|
||||
id = config.home,
|
||||
fields = Block.Fields(map = mapOf("name" to dashboardName)),
|
||||
type = Block.Content.Dashboard.Type.MAIN_SCREEN,
|
||||
type = Block.Content.Smart.Type.HOME,
|
||||
blocks = listOf(page),
|
||||
children = listOf(page.id)
|
||||
)
|
||||
|
@ -699,7 +719,7 @@ class HomeDashboardViewModelTest {
|
|||
val secondExpectedState = HomeDashboard(
|
||||
id = config.home,
|
||||
fields = Block.Fields(map = mapOf("name" to dashboardName)),
|
||||
type = Block.Content.Dashboard.Type.MAIN_SCREEN,
|
||||
type = Block.Content.Smart.Type.HOME,
|
||||
blocks = listOf(page, new),
|
||||
children = listOf(page.id)
|
||||
)
|
||||
|
@ -742,8 +762,27 @@ class HomeDashboardViewModelTest {
|
|||
}
|
||||
}
|
||||
|
||||
private fun stubOpenDashboard() {
|
||||
private fun stubOpenDashboard(
|
||||
payload: Payload = Payload(
|
||||
context = MockDataFactory.randomString(),
|
||||
events = emptyList()
|
||||
)
|
||||
) {
|
||||
openDashboard.stub {
|
||||
onBlocking { invoke(params = null) } doReturn Either.Right(payload)
|
||||
}
|
||||
}
|
||||
|
||||
private fun stubCreatePage(id: String) {
|
||||
createPage.stub {
|
||||
onBlocking { invoke(any(), any(), any()) } doAnswer { answer ->
|
||||
answer.getArgument<(Either<Throwable, String>) -> Unit>(2)(Either.Right(id))
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private fun stubCloseDashboard() {
|
||||
closeDashboard.stub {
|
||||
onBlocking { invoke(any(), any(), any()) } doAnswer { answer ->
|
||||
answer.getArgument<(Either<Throwable, Unit>) -> Unit>(2)(Either.Right(Unit))
|
||||
}
|
||||
|
|
|
@ -14,9 +14,6 @@ import kotlin.test.assertTrue
|
|||
|
||||
class HomeDashboardViewMapperTest {
|
||||
|
||||
@Mock
|
||||
lateinit var emojifier: Emojifier
|
||||
|
||||
@Before
|
||||
fun setup() {
|
||||
MockitoAnnotations.initMocks(this)
|
||||
|
@ -54,7 +51,7 @@ class HomeDashboardViewMapperTest {
|
|||
blocks = listOf(archived, active),
|
||||
children = listOf(archived.id, active.id),
|
||||
fields = Block.Fields.empty(),
|
||||
type = Block.Content.Dashboard.Type.MAIN_SCREEN,
|
||||
type = Block.Content.Smart.Type.HOME,
|
||||
details = Block.Details(
|
||||
details = mapOf(
|
||||
target to Block.Fields(
|
||||
|
@ -67,9 +64,7 @@ class HomeDashboardViewMapperTest {
|
|||
)
|
||||
|
||||
val result = runBlocking {
|
||||
dashboard.toView(
|
||||
emojifier = emojifier
|
||||
)
|
||||
dashboard.toView()
|
||||
}
|
||||
|
||||
assertTrue {
|
||||
|
|
|
@ -31,13 +31,11 @@ class DefaultBlockViewRendererTest {
|
|||
suspend fun render(
|
||||
root: Block,
|
||||
anchor: Id,
|
||||
counter: Counter = Counter.Default(),
|
||||
focus: Id,
|
||||
indent: Int
|
||||
): List<BlockView> = blocks.render(
|
||||
root = root,
|
||||
anchor = anchor,
|
||||
counter = counter,
|
||||
focus = focus,
|
||||
indent = indent
|
||||
)
|
||||
|
@ -63,8 +61,8 @@ class DefaultBlockViewRendererTest {
|
|||
MockitoAnnotations.initMocks(this)
|
||||
renderer = DefaultBlockViewRenderer(
|
||||
urlBuilder = UrlBuilder(config),
|
||||
emojifier = emojifier,
|
||||
toggleStateHolder = toggleStateHolder
|
||||
toggleStateHolder = toggleStateHolder,
|
||||
counter = Counter.Default()
|
||||
)
|
||||
}
|
||||
|
||||
|
|
File diff suppressed because it is too large
Load diff
|
@ -3,6 +3,8 @@ package anytype;
|
|||
option go_package = "pb";
|
||||
|
||||
import "models.proto";
|
||||
import "localstore.proto";
|
||||
import "events.proto";
|
||||
import "google/protobuf/struct.proto";
|
||||
|
||||
/*
|
||||
|
@ -24,7 +26,7 @@ message Rpc {
|
|||
|
||||
message Response {
|
||||
Error error = 1;
|
||||
|
||||
ResponseEvent event = 2;
|
||||
message Error {
|
||||
Code code = 1;
|
||||
string description = 2;
|
||||
|
@ -66,6 +68,30 @@ message Rpc {
|
|||
|
||||
message BlockList {
|
||||
|
||||
message ConvertChildrenToPages {
|
||||
message Request {
|
||||
string contextId = 1;
|
||||
repeated string blockIds = 2;
|
||||
}
|
||||
|
||||
message Response {
|
||||
Error error = 1;
|
||||
repeated string linkIds = 2;
|
||||
|
||||
message Error {
|
||||
Code code = 1;
|
||||
string description = 2;
|
||||
|
||||
enum Code {
|
||||
NULL = 0;
|
||||
UNKNOWN_ERROR = 1;
|
||||
BAD_INPUT = 2;
|
||||
// ...
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
message Move {
|
||||
message Request {
|
||||
string contextId = 1;
|
||||
|
@ -77,6 +103,7 @@ message Rpc {
|
|||
|
||||
message Response {
|
||||
Error error = 1;
|
||||
ResponseEvent event = 2;
|
||||
|
||||
message Error {
|
||||
Code code = 1;
|
||||
|
@ -96,14 +123,15 @@ message Rpc {
|
|||
message Request {
|
||||
string contextId = 1;
|
||||
repeated string blockIds = 2;
|
||||
anytype.model.Block block = 3;
|
||||
string dropTargetId = 4; // id of the block in Page(contextId) to create a link near that block
|
||||
google.protobuf.Struct details = 3; // page details
|
||||
string dropTargetId = 4;
|
||||
anytype.model.Block.Position position = 5;
|
||||
}
|
||||
|
||||
message Response {
|
||||
Error error = 1;
|
||||
string linkId = 2;
|
||||
ResponseEvent event = 3;
|
||||
|
||||
message Error {
|
||||
Code code = 1;
|
||||
|
@ -133,6 +161,7 @@ message Rpc {
|
|||
message Response {
|
||||
Error error = 1;
|
||||
repeated string blockIds = 2;
|
||||
ResponseEvent event = 3;
|
||||
|
||||
message Error {
|
||||
Code code = 1;
|
||||
|
@ -149,6 +178,32 @@ message Rpc {
|
|||
}
|
||||
|
||||
message Set {
|
||||
message Page {
|
||||
message IsArchived {
|
||||
message Request {
|
||||
string contextId = 1;
|
||||
repeated string blockIds = 2;
|
||||
bool isArchived = 3;
|
||||
}
|
||||
|
||||
message Response {
|
||||
Error error = 1;
|
||||
|
||||
message Error {
|
||||
Code code = 1;
|
||||
string description = 2;
|
||||
|
||||
enum Code {
|
||||
NULL = 0;
|
||||
UNKNOWN_ERROR = 1;
|
||||
BAD_INPUT = 2;
|
||||
// ...
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
message Text {
|
||||
message Style {
|
||||
message Request {
|
||||
|
@ -159,6 +214,7 @@ message Rpc {
|
|||
|
||||
message Response {
|
||||
Error error = 1;
|
||||
ResponseEvent event = 2;
|
||||
|
||||
message Error {
|
||||
Code code = 1;
|
||||
|
@ -182,6 +238,7 @@ message Rpc {
|
|||
|
||||
message Response {
|
||||
Error error = 1;
|
||||
ResponseEvent event = 2;
|
||||
|
||||
message Error {
|
||||
Code code = 1;
|
||||
|
@ -207,6 +264,7 @@ message Rpc {
|
|||
|
||||
message Response {
|
||||
Error error = 1;
|
||||
ResponseEvent event = 2;
|
||||
|
||||
message Error {
|
||||
Code code = 1;
|
||||
|
@ -230,6 +288,7 @@ message Rpc {
|
|||
|
||||
message Response {
|
||||
Error error = 1;
|
||||
ResponseEvent event = 2;
|
||||
|
||||
message Error {
|
||||
Code code = 1;
|
||||
|
@ -256,6 +315,60 @@ message Rpc {
|
|||
}
|
||||
message Response {
|
||||
Error error = 1;
|
||||
ResponseEvent event = 2;
|
||||
|
||||
message Error {
|
||||
Code code = 1;
|
||||
string description = 2;
|
||||
|
||||
enum Code {
|
||||
NULL = 0;
|
||||
UNKNOWN_ERROR = 1;
|
||||
BAD_INPUT = 2;
|
||||
// ...
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
message Div {
|
||||
message Style {
|
||||
message Request {
|
||||
string contextId = 1;
|
||||
repeated string blockIds = 2;
|
||||
anytype.model.Block.Content.Div.Style style = 3;
|
||||
}
|
||||
|
||||
message Response {
|
||||
Error error = 1;
|
||||
ResponseEvent event = 2;
|
||||
|
||||
message Error {
|
||||
Code code = 1;
|
||||
string description = 2;
|
||||
|
||||
enum Code {
|
||||
NULL = 0;
|
||||
UNKNOWN_ERROR = 1;
|
||||
BAD_INPUT = 2;
|
||||
// ...
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
message Delete {
|
||||
// Deletes the page, keys and all records from the local store and unsubscribe from remote changes
|
||||
message Page {
|
||||
message Request {
|
||||
repeated string blockIds = 1; // pages to remove
|
||||
}
|
||||
|
||||
message Response {
|
||||
Error error = 1;
|
||||
ResponseEvent event = 2;
|
||||
|
||||
message Error {
|
||||
Code code = 1;
|
||||
|
@ -287,6 +400,7 @@ message Rpc {
|
|||
message Response {
|
||||
Error error = 1;
|
||||
string blockId = 2;
|
||||
ResponseEvent event = 3;
|
||||
|
||||
message Error {
|
||||
Code code = 1;
|
||||
|
@ -302,18 +416,18 @@ message Rpc {
|
|||
}
|
||||
}
|
||||
|
||||
|
||||
message Split {
|
||||
message Request {
|
||||
string contextId = 1;
|
||||
string blockId = 2;
|
||||
int32 cursorPosition = 3;
|
||||
anytype.model.Range range = 3;
|
||||
anytype.model.Block.Content.Text.Style style = 4;
|
||||
}
|
||||
|
||||
message Response {
|
||||
Error error = 1;
|
||||
string blockId = 2;
|
||||
ResponseEvent event = 3;
|
||||
|
||||
message Error {
|
||||
Code code = 1;
|
||||
|
@ -338,6 +452,7 @@ message Rpc {
|
|||
|
||||
message Response {
|
||||
Error error = 1;
|
||||
ResponseEvent event = 2;
|
||||
|
||||
message Error {
|
||||
Code code = 1;
|
||||
|
@ -358,6 +473,7 @@ message Rpc {
|
|||
message Request {
|
||||
string contextId = 1;
|
||||
repeated anytype.model.Block blocks = 2;
|
||||
anytype.model.Range selectedTextRange = 3;
|
||||
}
|
||||
|
||||
message Response {
|
||||
|
@ -384,15 +500,18 @@ message Rpc {
|
|||
string focusedBlockId = 2;
|
||||
anytype.model.Range selectedTextRange = 3;
|
||||
repeated string selectedBlockIds = 4;
|
||||
anytype.model.Range copyTextRange = 5;
|
||||
|
||||
string textSlot = 5;
|
||||
string htmlSlot = 6;
|
||||
repeated anytype.model.Block anySlot = 7;
|
||||
string textSlot = 6;
|
||||
string htmlSlot = 7;
|
||||
repeated anytype.model.Block anySlot = 8;
|
||||
}
|
||||
|
||||
message Response {
|
||||
Error error = 1;
|
||||
repeated string blockIds = 2;
|
||||
int32 caretPosition = 3;
|
||||
ResponseEvent event = 4;
|
||||
|
||||
message Error {
|
||||
Code code = 1;
|
||||
|
@ -412,6 +531,7 @@ message Rpc {
|
|||
message Request {
|
||||
string contextId = 1;
|
||||
repeated anytype.model.Block blocks = 2;
|
||||
anytype.model.Range selectedTextRange = 3;
|
||||
}
|
||||
|
||||
message Response {
|
||||
|
@ -419,6 +539,7 @@ message Rpc {
|
|||
string textSlot = 2;
|
||||
string htmlSlot = 3;
|
||||
repeated anytype.model.Block anySlot = 4;
|
||||
ResponseEvent event = 5;
|
||||
|
||||
message Error {
|
||||
Code code = 1;
|
||||
|
@ -443,6 +564,7 @@ message Rpc {
|
|||
message Response {
|
||||
Error error = 1;
|
||||
string path = 2;
|
||||
ResponseEvent event = 3;
|
||||
|
||||
message Error {
|
||||
Code code = 1;
|
||||
|
@ -468,6 +590,7 @@ message Rpc {
|
|||
|
||||
message Response {
|
||||
Error error = 1;
|
||||
ResponseEvent event = 2;
|
||||
|
||||
message Error {
|
||||
Code code = 1;
|
||||
|
@ -491,6 +614,7 @@ message Rpc {
|
|||
|
||||
message Response {
|
||||
Error error = 1;
|
||||
ResponseEvent event = 2;
|
||||
|
||||
message Error {
|
||||
Code code = 1;
|
||||
|
@ -516,6 +640,7 @@ message Rpc {
|
|||
|
||||
message Response {
|
||||
Error error = 1;
|
||||
ResponseEvent event = 2;
|
||||
|
||||
message Error {
|
||||
Code code = 1;
|
||||
|
@ -564,6 +689,7 @@ message Rpc {
|
|||
|
||||
message Response {
|
||||
Error error = 1;
|
||||
ResponseEvent event = 2;
|
||||
|
||||
message Error {
|
||||
Code code = 1;
|
||||
|
@ -640,6 +766,7 @@ message Rpc {
|
|||
|
||||
message Response {
|
||||
Error error = 1;
|
||||
ResponseEvent event = 2;
|
||||
|
||||
message Error {
|
||||
Code code = 1;
|
||||
|
@ -665,6 +792,7 @@ message Rpc {
|
|||
|
||||
message Response {
|
||||
Error error = 1;
|
||||
ResponseEvent event = 2;
|
||||
|
||||
message Error {
|
||||
Code code = 1;
|
||||
|
@ -689,6 +817,7 @@ message Rpc {
|
|||
|
||||
message Response {
|
||||
Error error = 1;
|
||||
ResponseEvent event = 2;
|
||||
|
||||
message Error {
|
||||
Code code = 1;
|
||||
|
@ -715,6 +844,7 @@ message Rpc {
|
|||
|
||||
message Response {
|
||||
Error error = 1;
|
||||
ResponseEvent event = 2;
|
||||
|
||||
message Error {
|
||||
Code code = 1;
|
||||
|
@ -841,6 +971,7 @@ message Rpc {
|
|||
|
||||
message Response {
|
||||
Error error = 1;
|
||||
ResponseEvent event = 2;
|
||||
|
||||
message Error {
|
||||
Code code = 1;
|
||||
|
@ -858,6 +989,7 @@ message Rpc {
|
|||
}
|
||||
}
|
||||
|
||||
|
||||
message Bookmark {
|
||||
message Fetch {
|
||||
message Request {
|
||||
|
@ -868,6 +1000,63 @@ message Rpc {
|
|||
|
||||
message Response {
|
||||
Error error = 1;
|
||||
ResponseEvent event = 2;
|
||||
|
||||
message Error {
|
||||
Code code = 1;
|
||||
string description = 2;
|
||||
|
||||
enum Code {
|
||||
NULL = 0;
|
||||
UNKNOWN_ERROR = 1;
|
||||
BAD_INPUT = 2;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
message CreateAndFetch {
|
||||
message Request {
|
||||
string contextId = 1;
|
||||
string targetId = 2;
|
||||
anytype.model.Block.Position position = 3;
|
||||
string url = 4;
|
||||
}
|
||||
|
||||
message Response {
|
||||
Error error = 1;
|
||||
string blockId = 2;
|
||||
ResponseEvent event = 3;
|
||||
|
||||
message Error {
|
||||
Code code = 1;
|
||||
string description = 2;
|
||||
|
||||
enum Code {
|
||||
NULL = 0;
|
||||
UNKNOWN_ERROR = 1;
|
||||
BAD_INPUT = 2;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
message File {
|
||||
message CreateAndUpload {
|
||||
message Request {
|
||||
string contextId = 1;
|
||||
string targetId = 2;
|
||||
anytype.model.Block.Position position = 3;
|
||||
string url = 4;
|
||||
string localPath = 5;
|
||||
anytype.model.Block.Content.File.Type fileType = 6;
|
||||
}
|
||||
|
||||
message Response {
|
||||
Error error = 1;
|
||||
string blockId = 2;
|
||||
ResponseEvent event = 3;
|
||||
|
||||
message Error {
|
||||
Code code = 1;
|
||||
|
@ -896,6 +1085,7 @@ message Rpc {
|
|||
|
||||
message Response {
|
||||
Error error = 1;
|
||||
ResponseEvent event = 2;
|
||||
|
||||
message Error {
|
||||
Code code = 1;
|
||||
|
@ -919,6 +1109,7 @@ message Rpc {
|
|||
|
||||
message Response {
|
||||
Error error = 1;
|
||||
ResponseEvent event = 2;
|
||||
|
||||
message Error {
|
||||
Code code = 1;
|
||||
|
@ -942,6 +1133,7 @@ message Rpc {
|
|||
|
||||
message Response {
|
||||
Error error = 1;
|
||||
ResponseEvent event = 2;
|
||||
|
||||
message Error {
|
||||
Code code = 1;
|
||||
|
@ -979,12 +1171,35 @@ message Rpc {
|
|||
message Request {
|
||||
string contextId = 1; // id of the context blo1k
|
||||
string blockId = 2;
|
||||
repeated string breadcrumbsIds = 3; // optional ids of breadcrubms blocks
|
||||
}
|
||||
|
||||
message Response {
|
||||
Error error = 1;
|
||||
ResponseEvent event = 2;
|
||||
|
||||
message Error {
|
||||
Code code = 1;
|
||||
string description = 2;
|
||||
|
||||
enum Code {
|
||||
NULL = 0;
|
||||
UNKNOWN_ERROR = 1;
|
||||
BAD_INPUT = 2;
|
||||
// ...
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
message GetPublicWebURL {
|
||||
message Request {
|
||||
string blockId = 1;
|
||||
}
|
||||
|
||||
message Response {
|
||||
Error error = 1;
|
||||
|
||||
string url = 2;
|
||||
message Error {
|
||||
Code code = 1;
|
||||
string description = 2;
|
||||
|
@ -1007,6 +1222,7 @@ message Rpc {
|
|||
message Response {
|
||||
Error error = 1;
|
||||
string blockId = 2;
|
||||
ResponseEvent event = 3;
|
||||
|
||||
message Error {
|
||||
Code code = 1;
|
||||
|
@ -1022,14 +1238,15 @@ message Rpc {
|
|||
}
|
||||
}
|
||||
|
||||
message CutBreadcrumbs {
|
||||
message SetBreadcrumbs {
|
||||
message Request {
|
||||
string breadcrumbsId = 1;
|
||||
int32 index = 2; // 0 - for full reset
|
||||
repeated string ids = 2; // page ids
|
||||
}
|
||||
|
||||
message Response {
|
||||
Error error = 1;
|
||||
ResponseEvent event = 2;
|
||||
|
||||
message Error {
|
||||
Code code = 1;
|
||||
|
@ -1071,6 +1288,7 @@ message Rpc {
|
|||
message Response {
|
||||
Error error = 1;
|
||||
string blockId = 2;
|
||||
ResponseEvent event = 3;
|
||||
|
||||
message Error {
|
||||
Code code = 1;
|
||||
|
@ -1098,6 +1316,7 @@ message Rpc {
|
|||
Error error = 1;
|
||||
string blockId = 2;
|
||||
string targetId = 3;
|
||||
ResponseEvent event = 4;
|
||||
|
||||
message Error {
|
||||
Code code = 1;
|
||||
|
@ -1112,6 +1331,7 @@ message Rpc {
|
|||
}
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* Remove blocks from the childrenIds of its parents
|
||||
*/
|
||||
|
@ -1124,6 +1344,7 @@ message Rpc {
|
|||
|
||||
message Response {
|
||||
Error error = 1;
|
||||
ResponseEvent event = 2;
|
||||
|
||||
message Error {
|
||||
Code code = 1;
|
||||
|
@ -1246,6 +1467,9 @@ message Rpc {
|
|||
string avatarLocalPath = 2; // Path to an image, that will be used as an avatar of this account
|
||||
string avatarColor = 3; // Avatar color as an alternative for avatar image
|
||||
}
|
||||
|
||||
|
||||
string alphaInviteCode = 20;
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -1269,6 +1493,7 @@ message Rpc {
|
|||
ACCOUNT_CREATED_BUT_FAILED_TO_SET_AVATAR = 103;
|
||||
FAILED_TO_STOP_RUNNING_NODE = 104;
|
||||
|
||||
BAD_INVITE_CODE = 900;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -1544,6 +1769,27 @@ message Rpc {
|
|||
}
|
||||
}
|
||||
|
||||
message Shutdown {
|
||||
message Request {
|
||||
}
|
||||
message Response {
|
||||
Error error = 1;
|
||||
|
||||
message Error {
|
||||
Code code = 1;
|
||||
string description = 2;
|
||||
enum Code {
|
||||
NULL = 0;
|
||||
UNKNOWN_ERROR = 1;
|
||||
BAD_INPUT = 2;
|
||||
|
||||
NODE_NOT_STARTED = 101;
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
message Config {
|
||||
message Get {
|
||||
message Request {
|
||||
|
@ -1551,7 +1797,8 @@ message Rpc {
|
|||
message Response {
|
||||
Error error = 1;
|
||||
string homeBlockId = 2; // home dashboard block id
|
||||
string archiveBlockId = 3; // home dashboard block id
|
||||
string archiveBlockId = 3; // archive block id
|
||||
string profileBlockId = 4; // profile block id
|
||||
string gatewayUrl = 101; // gateway url for fetching static files
|
||||
message Error {
|
||||
Code code = 1;
|
||||
|
@ -1564,7 +1811,6 @@ message Rpc {
|
|||
NODE_NOT_STARTED = 101;
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -1643,6 +1889,7 @@ message Rpc {
|
|||
string url = 1;
|
||||
string localPath = 2;
|
||||
anytype.model.Block.Content.File.Type type = 3;
|
||||
bool disableEncryption = 4;
|
||||
}
|
||||
|
||||
message Response {
|
||||
|
@ -1662,6 +1909,55 @@ message Rpc {
|
|||
}
|
||||
}
|
||||
|
||||
message Navigation {
|
||||
message ListPages {
|
||||
message Request {
|
||||
}
|
||||
|
||||
message Response {
|
||||
Error error = 1;
|
||||
repeated anytype.model.PageInfo pages = 2;
|
||||
|
||||
message Error {
|
||||
Code code = 1;
|
||||
string description = 2;
|
||||
|
||||
enum Code {
|
||||
NULL = 0;
|
||||
UNKNOWN_ERROR = 1;
|
||||
BAD_INPUT = 2;
|
||||
// ...
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* Get the info for page alongside with info for all inbound and outbound links from/to this page
|
||||
*/
|
||||
message GetPageInfoWithLinks {
|
||||
message Request {
|
||||
string pageId = 1;
|
||||
}
|
||||
|
||||
message Response {
|
||||
Error error = 1;
|
||||
anytype.model.PageInfoWithLinks page = 2;
|
||||
|
||||
message Error {
|
||||
Code code = 1;
|
||||
string description = 2;
|
||||
|
||||
enum Code {
|
||||
NULL = 0;
|
||||
UNKNOWN_ERROR = 1;
|
||||
BAD_INPUT = 2;
|
||||
// ...
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
message Empty {
|
||||
|
|
|
@ -16,6 +16,7 @@ message Event {
|
|||
message Message {
|
||||
oneof value {
|
||||
Account.Show accountShow = 1;
|
||||
Account.Details accountDetails = 201;
|
||||
|
||||
Block.Add blockAdd = 2;
|
||||
Block.Delete blockDelete = 3;
|
||||
|
@ -33,6 +34,7 @@ message Event {
|
|||
Block.Set.Bookmark blockSetBookmark = 14;
|
||||
Block.Set.Align blockSetAlign = 15;
|
||||
Block.Set.Details blockSetDetails = 16;
|
||||
Block.Set.Div blockSetDiv = 17;
|
||||
|
||||
Block.Show blockShow = 20;
|
||||
User.Block.Join userBlockJoin = 21;
|
||||
|
@ -56,6 +58,11 @@ message Event {
|
|||
int32 index = 1; // Number of an account in an all found accounts list
|
||||
anytype.model.Account account = 2; // An Account, that has been found for the mnemonic
|
||||
}
|
||||
|
||||
message Details {
|
||||
string profileId = 1;
|
||||
google.protobuf.Struct details = 2;
|
||||
}
|
||||
}
|
||||
message Block {
|
||||
/*
|
||||
|
@ -75,13 +82,14 @@ message Event {
|
|||
}
|
||||
|
||||
/*
|
||||
* Works with a smart blocks: Page, Dashboard
|
||||
* Dashboard opened, click on a page, Rpc.Block.open, Block.ShowFullscreen(PageBlock)
|
||||
* Works with a smart blocks: Page, Dashboard
|
||||
* Dashboard opened, click on a page, Rpc.Block.open, Block.ShowFullscreen(PageBlock)
|
||||
*/
|
||||
message Show {
|
||||
string rootId = 1; // Root block id
|
||||
repeated anytype.model.Block blocks = 2; // dependent blocks (descendants)
|
||||
repeated Block.Set.Details details = 3; // details for current and dependent smart blocks
|
||||
SmartBlockType type = 4;
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -169,6 +177,16 @@ message Event {
|
|||
|
||||
}
|
||||
|
||||
message Div {
|
||||
string id = 1;
|
||||
Style style = 2;
|
||||
|
||||
message Style {
|
||||
anytype.model.Block.Content.Div.Style value = 1;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
message File {
|
||||
string id = 1;
|
||||
Type type = 2;
|
||||
|
@ -331,6 +349,19 @@ message Event {
|
|||
|
||||
}
|
||||
|
||||
enum SmartBlockType {
|
||||
Page = 0;
|
||||
Home = 1;
|
||||
ProfilePage = 2;
|
||||
Archive = 3;
|
||||
Breadcrumbs = 4;
|
||||
}
|
||||
|
||||
message ResponseEvent {
|
||||
repeated Event.Message messages = 1;
|
||||
string contextId = 2;
|
||||
}
|
||||
|
||||
message Model {
|
||||
message Process {
|
||||
string id = 1;
|
||||
|
@ -355,4 +386,4 @@ message Model {
|
|||
int64 done = 2;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
53
protobuf/src/main/proto/localstore.proto
Executable file
53
protobuf/src/main/proto/localstore.proto
Executable file
|
@ -0,0 +1,53 @@
|
|||
syntax = "proto3";
|
||||
package anytype.model;
|
||||
option go_package = "github.com/anytypeio/go-anytype-library/pb/model";
|
||||
|
||||
import "google/protobuf/struct.proto";
|
||||
|
||||
message State {
|
||||
map<string, uint64> state = 1;
|
||||
}
|
||||
|
||||
message PageInfo {
|
||||
string id = 1;
|
||||
google.protobuf.Struct details = 2;
|
||||
string snippet = 3;
|
||||
State state = 4;
|
||||
int64 lastOpened = 5;
|
||||
uint32 inboundLinksCount = 6;
|
||||
}
|
||||
|
||||
message PageDetails {
|
||||
google.protobuf.Struct details = 1;
|
||||
}
|
||||
|
||||
message PageLinks {
|
||||
repeated string inboundIDs = 1;
|
||||
repeated string outboundIDs = 2;
|
||||
}
|
||||
|
||||
message PageLinksInfo {
|
||||
repeated PageInfo inbound = 1;
|
||||
repeated PageInfo outbound = 2;
|
||||
}
|
||||
|
||||
message PageInfoWithLinks {
|
||||
string id = 1;
|
||||
PageInfo info = 2;
|
||||
PageLinksInfo links = 3;
|
||||
State state = 4;
|
||||
}
|
||||
|
||||
message PageInfoWithOutboundLinks {
|
||||
string id = 1;
|
||||
PageInfo info = 2;
|
||||
repeated PageInfo outboundLinks = 3;
|
||||
State state = 4;
|
||||
}
|
||||
|
||||
message PageInfoWithOutboundLinksIDs {
|
||||
string id = 1;
|
||||
PageInfo info = 2;
|
||||
repeated string outboundLinks = 3;
|
||||
State state = 4;
|
||||
}
|
|
@ -4,16 +4,10 @@ option go_package = "github.com/anytypeio/go-anytype-library/pb/model";
|
|||
|
||||
import "google/protobuf/struct.proto";
|
||||
|
||||
message SmartBlock {
|
||||
string id = 1;
|
||||
Type type = 2;
|
||||
enum Type {
|
||||
Dashboard = 0;
|
||||
Page = 1;
|
||||
Archive = 2;
|
||||
Breadcrumbs = 3;
|
||||
Dataview = 4;
|
||||
}
|
||||
message SmartBlockSnapshotBase {
|
||||
repeated Block blocks = 1;
|
||||
google.protobuf.Struct details = 2;
|
||||
google.protobuf.Struct fileKeys = 3;
|
||||
}
|
||||
|
||||
message Block {
|
||||
|
@ -25,9 +19,7 @@ message Block {
|
|||
Align align = 6;
|
||||
|
||||
oneof content {
|
||||
Content.Dashboard dashboard = 11;
|
||||
Content.Page page = 12;
|
||||
Content.Dataview dataview = 13;
|
||||
Content.Smartblock smartblock = 11;
|
||||
|
||||
Content.Text text = 14;
|
||||
Content.File file = 15;
|
||||
|
@ -36,6 +28,7 @@ message Block {
|
|||
Content.Bookmark bookmark = 18;
|
||||
Content.Icon icon = 19;
|
||||
Content.Link link = 20;
|
||||
Content.Dataview dataview = 21;
|
||||
}
|
||||
|
||||
|
||||
|
@ -74,6 +67,7 @@ message Block {
|
|||
enum Style {
|
||||
Row = 0;
|
||||
Column = 1;
|
||||
Div = 2;
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -122,22 +116,6 @@ message Block {
|
|||
string name = 1;
|
||||
}
|
||||
|
||||
/*
|
||||
* Block type to organize pages on the main screen (main purpose)
|
||||
* It also can be mounted on a page.
|
||||
*/
|
||||
message Dashboard {
|
||||
enum Style {
|
||||
MainScreen = 0;
|
||||
Archive = 1;
|
||||
}
|
||||
|
||||
Style style = 1;
|
||||
}
|
||||
|
||||
message Dataview {
|
||||
}
|
||||
|
||||
message Text {
|
||||
string text = 1;
|
||||
Style style = 2;
|
||||
|
@ -207,19 +185,11 @@ message Block {
|
|||
}
|
||||
}
|
||||
|
||||
message Page {
|
||||
enum Style {
|
||||
Empty = 0; // Ordinary page, without additional fields
|
||||
Task = 1; // Page with a task fields
|
||||
Set = 2; // Page, that organize a set of blocks by a specific criterio
|
||||
Profile = 3;
|
||||
message Smartblock {
|
||||
}
|
||||
|
||||
Breadcrumbs = 101;
|
||||
|
||||
// ...
|
||||
}
|
||||
|
||||
Style style = 1;
|
||||
message Dataview {
|
||||
string databaseId = 1;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,5 +1,4 @@
|
|||
include ':app', ':library-emojifier',
|
||||
':sample',
|
||||
include ':app',
|
||||
':core-utils',
|
||||
':middleware',
|
||||
':protobuf',
|
||||
|
@ -8,6 +7,9 @@ include ':app', ':library-emojifier',
|
|||
':data',
|
||||
':device',
|
||||
':presentation',
|
||||
':presentation-editor',
|
||||
':core-ui',
|
||||
':library-kanban-widget',
|
||||
':library-page-icon-picker-widget'
|
||||
':library-page-icon-picker-widget',
|
||||
':library-emojifier',
|
||||
':sample'
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue