mirror of
https://github.com/anyproto/anytype-kotlin.git
synced 2025-06-08 05:47:05 +09:00
Editor | Feature | Note as main type (#1852)
* update proto * add layout note * add title note * send default type on pageCreate * title can be null * fixes * test * drawables * object layout screen * footer adapter * mapping * get layouts use case * fix * update createPage use case * default page type on dashboard * default page type on editor * fix tests * notes layout logic * fix * hide on text change * fix * fix * fix test * fix * fix * fix test * fix * ci off * fix * pr fix * fix * fix * fixes * fix * fix * fix * fix test * ci off
This commit is contained in:
parent
8a4f0e05eb
commit
8076d126f0
42 changed files with 732 additions and 218 deletions
|
@ -60,6 +60,7 @@ object EventsDictionary {
|
|||
|
||||
const val PROP_STYLE = "style"
|
||||
const val PROP_TYPE = "objectType"
|
||||
const val PROP_IS_DRAFT = "isDraft"
|
||||
const val PROP_LAYOUT = "layout"
|
||||
const val PROP_ACCOUNT_ID = "accountId"
|
||||
const val PROP_RELATION_FORMAT = "relationFormat"
|
||||
|
|
|
@ -10,11 +10,12 @@ import com.anytypeio.anytype.domain.block.repo.BlockRepository
|
|||
import com.anytypeio.anytype.domain.config.GetConfig
|
||||
import com.anytypeio.anytype.domain.config.GetDebugSettings
|
||||
import com.anytypeio.anytype.domain.config.InfrastructureRepository
|
||||
import com.anytypeio.anytype.domain.config.UserSettingsRepository
|
||||
import com.anytypeio.anytype.domain.dashboard.interactor.*
|
||||
import com.anytypeio.anytype.domain.dataview.interactor.SearchObjects
|
||||
import com.anytypeio.anytype.domain.event.interactor.EventChannel
|
||||
import com.anytypeio.anytype.domain.event.interactor.InterceptEvents
|
||||
import com.anytypeio.anytype.domain.icon.DocumentEmojiIconProvider
|
||||
import com.anytypeio.anytype.domain.launch.GetDefaultEditorType
|
||||
import com.anytypeio.anytype.domain.misc.UrlBuilder
|
||||
import com.anytypeio.anytype.domain.objects.DeleteObjects
|
||||
import com.anytypeio.anytype.domain.objects.SetObjectListIsArchived
|
||||
|
@ -61,6 +62,7 @@ object HomeDashboardModule {
|
|||
getDebugSettings: GetDebugSettings,
|
||||
analytics: Analytics,
|
||||
searchObjects: SearchObjects,
|
||||
getDefaultEditorType: GetDefaultEditorType,
|
||||
urlBuilder: UrlBuilder,
|
||||
setObjectListIsArchived: SetObjectListIsArchived,
|
||||
deleteObjects: DeleteObjects
|
||||
|
@ -78,7 +80,8 @@ object HomeDashboardModule {
|
|||
analytics = analytics,
|
||||
urlBuilder = urlBuilder,
|
||||
setObjectListIsArchived = setObjectListIsArchived,
|
||||
deleteObjects = deleteObjects
|
||||
deleteObjects = deleteObjects,
|
||||
getDefaultEditorType = getDefaultEditorType
|
||||
)
|
||||
|
||||
@JvmStatic
|
||||
|
@ -178,6 +181,12 @@ object HomeDashboardModule {
|
|||
repo = repo
|
||||
)
|
||||
|
||||
@JvmStatic
|
||||
@Provides
|
||||
@PerScreen
|
||||
fun provideGetDefaultPageType(repo: UserSettingsRepository): GetDefaultEditorType =
|
||||
GetDefaultEditorType(repo)
|
||||
|
||||
@JvmStatic
|
||||
@Provides
|
||||
@PerScreen
|
||||
|
|
|
@ -20,6 +20,7 @@ import com.anytypeio.anytype.domain.block.repo.BlockRepository
|
|||
import com.anytypeio.anytype.domain.clipboard.Clipboard
|
||||
import com.anytypeio.anytype.domain.clipboard.Copy
|
||||
import com.anytypeio.anytype.domain.clipboard.Paste
|
||||
import com.anytypeio.anytype.domain.config.UserSettingsRepository
|
||||
import com.anytypeio.anytype.domain.dataview.interactor.GetCompatibleObjectTypes
|
||||
import com.anytypeio.anytype.domain.dataview.interactor.SearchObjects
|
||||
import com.anytypeio.anytype.domain.dataview.interactor.SetRelationKey
|
||||
|
@ -28,6 +29,7 @@ import com.anytypeio.anytype.domain.download.Downloader
|
|||
import com.anytypeio.anytype.domain.event.interactor.EventChannel
|
||||
import com.anytypeio.anytype.domain.event.interactor.InterceptEvents
|
||||
import com.anytypeio.anytype.domain.icon.DocumentEmojiIconProvider
|
||||
import com.anytypeio.anytype.domain.launch.GetDefaultEditorType
|
||||
import com.anytypeio.anytype.domain.misc.UrlBuilder
|
||||
import com.anytypeio.anytype.domain.objects.SetObjectIsArchived
|
||||
import com.anytypeio.anytype.domain.page.*
|
||||
|
@ -144,7 +146,8 @@ object EditorSessionModule {
|
|||
updateDetail: UpdateDetail,
|
||||
getCompatibleObjectTypes: GetCompatibleObjectTypes,
|
||||
objectTypesProvider: ObjectTypesProvider,
|
||||
searchObjects: SearchObjects
|
||||
searchObjects: SearchObjects,
|
||||
getDefaultEditorType: GetDefaultEditorType
|
||||
): EditorViewModelFactory = EditorViewModelFactory(
|
||||
openPage = openPage,
|
||||
closeObject = closePage,
|
||||
|
@ -167,7 +170,8 @@ object EditorSessionModule {
|
|||
updateDetail = updateDetail,
|
||||
getCompatibleObjectTypes = getCompatibleObjectTypes,
|
||||
objectTypesProvider = objectTypesProvider,
|
||||
searchObjects = searchObjects
|
||||
searchObjects = searchObjects,
|
||||
getDefaultEditorType = getDefaultEditorType
|
||||
)
|
||||
|
||||
@JvmStatic
|
||||
|
@ -726,4 +730,10 @@ object EditorUseCaseModule {
|
|||
fun searchObjects(
|
||||
repo: BlockRepository
|
||||
): SearchObjects = SearchObjects(repo = repo)
|
||||
|
||||
@JvmStatic
|
||||
@Provides
|
||||
@PerScreen
|
||||
fun provideGetDefaultPageType(repo: UserSettingsRepository): GetDefaultEditorType =
|
||||
GetDefaultEditorType(repo)
|
||||
}
|
|
@ -13,11 +13,10 @@ import com.anytypeio.anytype.domain.block.repo.BlockRepository
|
|||
import com.anytypeio.anytype.domain.config.FlavourConfigProvider
|
||||
import com.anytypeio.anytype.domain.config.UserSettingsRepository
|
||||
import com.anytypeio.anytype.domain.device.PathProvider
|
||||
import com.anytypeio.anytype.domain.launch.GetDefaultPageType
|
||||
import com.anytypeio.anytype.domain.launch.SetDefaultPageType
|
||||
import com.anytypeio.anytype.domain.launch.GetDefaultEditorType
|
||||
import com.anytypeio.anytype.domain.launch.SetDefaultEditorType
|
||||
import com.anytypeio.anytype.presentation.splash.SplashViewModelFactory
|
||||
import com.anytypeio.anytype.ui.splash.SplashFragment
|
||||
import com.squareup.wire.get
|
||||
import dagger.Module
|
||||
import dagger.Provides
|
||||
import dagger.Subcomponent
|
||||
|
@ -54,8 +53,8 @@ object SplashModule {
|
|||
analytics: Analytics,
|
||||
storeObjectTypes: StoreObjectTypes,
|
||||
getLastOpenedObject: GetLastOpenedObject,
|
||||
getDefaultPageType: GetDefaultPageType,
|
||||
setDefaultPageType: SetDefaultPageType
|
||||
getDefaultEditorType: GetDefaultEditorType,
|
||||
setDefaultEditorType: SetDefaultEditorType
|
||||
): SplashViewModelFactory = SplashViewModelFactory(
|
||||
checkAuthorizationStatus = checkAuthorizationStatus,
|
||||
launchAccount = launchAccount,
|
||||
|
@ -63,8 +62,8 @@ object SplashModule {
|
|||
analytics = analytics,
|
||||
storeObjectTypes = storeObjectTypes,
|
||||
getLastOpenedObject = getLastOpenedObject,
|
||||
setDefaultPageType = setDefaultPageType,
|
||||
getDefaultPageType = getDefaultPageType
|
||||
setDefaultEditorType = setDefaultEditorType,
|
||||
getDefaultEditorType = getDefaultEditorType
|
||||
)
|
||||
|
||||
@JvmStatic
|
||||
|
@ -123,12 +122,12 @@ object SplashModule {
|
|||
@JvmStatic
|
||||
@PerScreen
|
||||
@Provides
|
||||
fun provideGetDefaultPageType(repo: UserSettingsRepository): GetDefaultPageType =
|
||||
GetDefaultPageType(repo)
|
||||
fun provideGetDefaultPageType(repo: UserSettingsRepository): GetDefaultEditorType =
|
||||
GetDefaultEditorType(repo)
|
||||
|
||||
@JvmStatic
|
||||
@PerScreen
|
||||
@Provides
|
||||
fun provideSetDefaultPageType(repo: UserSettingsRepository): SetDefaultPageType =
|
||||
SetDefaultPageType(repo)
|
||||
fun provideSetDefaultPageType(repo: UserSettingsRepository): SetDefaultEditorType =
|
||||
SetDefaultEditorType(repo)
|
||||
}
|
|
@ -3,8 +3,8 @@ package com.anytypeio.anytype.di.feature
|
|||
import com.anytypeio.anytype.analytics.base.Analytics
|
||||
import com.anytypeio.anytype.core_utils.di.scope.PerScreen
|
||||
import com.anytypeio.anytype.domain.config.UserSettingsRepository
|
||||
import com.anytypeio.anytype.domain.launch.GetDefaultPageType
|
||||
import com.anytypeio.anytype.domain.launch.SetDefaultPageType
|
||||
import com.anytypeio.anytype.domain.launch.GetDefaultEditorType
|
||||
import com.anytypeio.anytype.domain.launch.SetDefaultEditorType
|
||||
import com.anytypeio.anytype.presentation.settings.UserSettingsViewModel
|
||||
import com.anytypeio.anytype.ui.settings.UserSettingsFragment
|
||||
import dagger.Module
|
||||
|
@ -30,22 +30,22 @@ object UserSettingsModule {
|
|||
@JvmStatic
|
||||
@PerScreen
|
||||
@Provides
|
||||
fun provideGetDefaultPageType(repo: UserSettingsRepository): GetDefaultPageType =
|
||||
GetDefaultPageType(repo)
|
||||
fun provideGetDefaultPageType(repo: UserSettingsRepository): GetDefaultEditorType =
|
||||
GetDefaultEditorType(repo)
|
||||
|
||||
@JvmStatic
|
||||
@PerScreen
|
||||
@Provides
|
||||
fun provideSetDefaultPageType(repo: UserSettingsRepository): SetDefaultPageType =
|
||||
SetDefaultPageType(repo)
|
||||
fun provideSetDefaultPageType(repo: UserSettingsRepository): SetDefaultEditorType =
|
||||
SetDefaultEditorType(repo)
|
||||
|
||||
@JvmStatic
|
||||
@Provides
|
||||
@PerScreen
|
||||
fun provideUserSettingsFabric(
|
||||
getDefaultPageType: GetDefaultPageType,
|
||||
setDefaultPageType: SetDefaultPageType,
|
||||
getDefaultEditorType: GetDefaultEditorType,
|
||||
setDefaultEditorType: SetDefaultEditorType,
|
||||
analytics: Analytics
|
||||
): UserSettingsViewModel.Factory =
|
||||
UserSettingsViewModel.Factory(getDefaultPageType, setDefaultPageType, analytics)
|
||||
UserSettingsViewModel.Factory(getDefaultEditorType, setDefaultEditorType, analytics)
|
||||
}
|
|
@ -47,6 +47,7 @@ object BlockActionToolbarFactory {
|
|||
is BlockView.Description -> TODO()
|
||||
is BlockView.FeaturedRelation -> TODO()
|
||||
is BlockView.Unsupported -> TODO()
|
||||
is BlockView.TitleNote -> TODO()
|
||||
}
|
||||
|
||||
fun newInstance(
|
||||
|
|
|
@ -52,16 +52,15 @@ fun List<Block>.parents(selection: Iterable<Id>) : List<Id> {
|
|||
|
||||
/**
|
||||
* Finds title block for a [Document]
|
||||
* @return title block
|
||||
* @throws NoSuchElementException if there was no title block in this document.
|
||||
* @return title block or null if there's no title present
|
||||
*/
|
||||
fun Document.title(): Block {
|
||||
val header = first { block ->
|
||||
fun Document.title(): Block? {
|
||||
val header = firstOrNull { block ->
|
||||
val cnt = block.content
|
||||
cnt is Content.Layout && cnt.type == Content.Layout.Type.HEADER
|
||||
}
|
||||
} ?: return null
|
||||
val children = filter { header.children.contains(it.id) }
|
||||
return children.first { child ->
|
||||
return children.firstOrNull { child ->
|
||||
val cnt = child.content
|
||||
cnt is Content.Text && cnt.style == Content.Text.Style.TITLE
|
||||
}
|
||||
|
|
|
@ -76,6 +76,7 @@ import com.anytypeio.anytype.presentation.editor.editor.mention.MentionEvent
|
|||
import com.anytypeio.anytype.presentation.editor.editor.model.BlockView
|
||||
import com.anytypeio.anytype.presentation.editor.editor.model.Types.HOLDER_DESCRIPTION
|
||||
import com.anytypeio.anytype.presentation.editor.editor.model.Types.HOLDER_FEATURED_RELATION
|
||||
import com.anytypeio.anytype.presentation.editor.editor.model.Types.HOLDER_NOTE_TITLE
|
||||
import com.anytypeio.anytype.presentation.editor.editor.model.Types.HOLDER_RELATION_CHECKBOX
|
||||
import com.anytypeio.anytype.presentation.editor.editor.model.Types.HOLDER_RELATION_DEFAULT
|
||||
import com.anytypeio.anytype.presentation.editor.editor.model.Types.HOLDER_RELATION_FILE
|
||||
|
@ -251,6 +252,15 @@ class BlockAdapter(
|
|||
}
|
||||
}
|
||||
}
|
||||
HOLDER_NOTE_TITLE -> {
|
||||
TitleNoteHolder(
|
||||
view = inflater.inflate(
|
||||
R.layout.item_block_note_title,
|
||||
parent,
|
||||
false
|
||||
)
|
||||
)
|
||||
}
|
||||
HOLDER_HEADER_ONE -> {
|
||||
HeaderOne(
|
||||
view = inflater.inflate(
|
||||
|
|
|
@ -0,0 +1,6 @@
|
|||
package com.anytypeio.anytype.core_ui.features.editor.holders.other
|
||||
|
||||
import android.view.View
|
||||
import com.anytypeio.anytype.core_ui.features.editor.BlockViewHolder
|
||||
|
||||
class TitleNoteHolder(view: View) : BlockViewHolder(view)
|
5
core-ui/src/main/res/layout/item_block_note_title.xml
Normal file
5
core-ui/src/main/res/layout/item_block_note_title.xml
Normal file
|
@ -0,0 +1,5 @@
|
|||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<FrameLayout xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="124dp">
|
||||
</FrameLayout>
|
|
@ -42,10 +42,11 @@ class BlockDataRepository(
|
|||
command: Command.UpdateAlignment
|
||||
): Payload = factory.remote.updateAlignment(command)
|
||||
|
||||
override suspend fun createPage(ctx: Id?, emoji: String?, isDraft: Boolean?) = factory.remote.createPage(
|
||||
override suspend fun createPage(ctx: Id?, emoji: String?, isDraft: Boolean?, type: String?) = factory.remote.createPage(
|
||||
ctx = ctx,
|
||||
emoji = emoji,
|
||||
isDraft = isDraft
|
||||
isDraft = isDraft,
|
||||
type = type
|
||||
)
|
||||
|
||||
override suspend fun closePage(id: String) {
|
||||
|
|
|
@ -26,7 +26,7 @@ interface BlockDataStore {
|
|||
suspend fun move(command: Command.Move): Payload
|
||||
suspend fun unlink(command: Command.Unlink): Payload
|
||||
suspend fun getConfig(): Config
|
||||
suspend fun createPage(ctx: Id?, emoji: String?, isDraft: Boolean?): Id
|
||||
suspend fun createPage(ctx: Id?, emoji: String?, isDraft: Boolean?, type: String?): Id
|
||||
suspend fun openPage(id: String): Payload
|
||||
suspend fun openObjectSet(id: String): Payload
|
||||
suspend fun openProfile(id: String): Payload
|
||||
|
|
|
@ -23,7 +23,7 @@ interface BlockRemote {
|
|||
suspend fun updateCheckbox(command: Command.UpdateCheckbox): Payload
|
||||
suspend fun move(command: Command.Move): Payload
|
||||
suspend fun getConfig(): Config
|
||||
suspend fun createPage(ctx: Id?, emoji: String?, isDraft: Boolean?): Id
|
||||
suspend fun createPage(ctx: Id?, emoji: String?, isDraft: Boolean?, type: String?): Id
|
||||
suspend fun createPage(command: Command.CreateNewDocument): String
|
||||
suspend fun openPage(id: String): Payload
|
||||
suspend fun openProfile(id: String): Payload
|
||||
|
|
|
@ -18,8 +18,9 @@ class BlockRemoteDataStore(private val remote: BlockRemote) : BlockDataStore {
|
|||
override suspend fun createPage(
|
||||
ctx: Id?,
|
||||
emoji: String?,
|
||||
isDraft: Boolean?
|
||||
): Id = remote.createPage(ctx = ctx, emoji = emoji, isDraft = isDraft)
|
||||
isDraft: Boolean?,
|
||||
type: String?
|
||||
): Id = remote.createPage(ctx = ctx, emoji = emoji, isDraft = isDraft, type = type)
|
||||
|
||||
override suspend fun openPage(id: String): Payload = remote.openPage(id)
|
||||
override suspend fun openProfile(id: String): Payload = remote.openProfile(id)
|
||||
|
|
|
@ -69,7 +69,7 @@ interface BlockRepository {
|
|||
|
||||
suspend fun getConfig(): Config
|
||||
|
||||
suspend fun createPage(ctx: Id?, emoji: String?, isDraft: Boolean?): Id
|
||||
suspend fun createPage(ctx: Id?, emoji: String?, isDraft: Boolean?, type: String?): Id
|
||||
|
||||
suspend fun openPage(id: String): Result<Payload>
|
||||
|
||||
|
|
|
@ -3,9 +3,9 @@ package com.anytypeio.anytype.domain.launch
|
|||
import com.anytypeio.anytype.domain.base.BaseUseCase
|
||||
import com.anytypeio.anytype.domain.config.UserSettingsRepository
|
||||
|
||||
class GetDefaultPageType(
|
||||
class GetDefaultEditorType(
|
||||
private val userSettingsRepository: UserSettingsRepository
|
||||
) : BaseUseCase<GetDefaultPageType.Response, Unit>() {
|
||||
) : BaseUseCase<GetDefaultEditorType.Response, Unit>() {
|
||||
|
||||
override suspend fun run(params: Unit) = safe {
|
||||
Response(userSettingsRepository.getDefaultPageType())
|
|
@ -3,8 +3,8 @@ package com.anytypeio.anytype.domain.launch
|
|||
import com.anytypeio.anytype.domain.base.BaseUseCase
|
||||
import com.anytypeio.anytype.domain.config.UserSettingsRepository
|
||||
|
||||
class SetDefaultPageType(private val repo: UserSettingsRepository) :
|
||||
BaseUseCase<Unit, SetDefaultPageType.Params>() {
|
||||
class SetDefaultEditorType(private val repo: UserSettingsRepository) :
|
||||
BaseUseCase<Unit, SetDefaultEditorType.Params>() {
|
||||
|
||||
override suspend fun run(params: Params) = safe {
|
||||
repo.setDefaultPageType(params.type)
|
|
@ -16,12 +16,20 @@ class CreatePage(
|
|||
repo.createPage(
|
||||
ctx = params.ctx,
|
||||
emoji = null,
|
||||
isDraft = params.isDraft
|
||||
isDraft = params.isDraft,
|
||||
type = params.type
|
||||
)
|
||||
}
|
||||
|
||||
/**
|
||||
* @property [ctx] context (parent) for this new page.
|
||||
* @property [type] type of created object
|
||||
* @property [isDraft] should this object be in Draft state
|
||||
*/
|
||||
data class Params(val ctx: Id?, val isDraft: Boolean?)
|
||||
data class Params(
|
||||
val ctx: Id?,
|
||||
val type: String?,
|
||||
val emoji: String?,
|
||||
val isDraft: Boolean?
|
||||
)
|
||||
}
|
|
@ -947,8 +947,8 @@ class BlockExtensionTest {
|
|||
assertEquals(expected = expected, actual = result)
|
||||
}
|
||||
|
||||
@Test(expected = NoSuchElementException::class)
|
||||
fun `should throw NoSuchElementException when title block is not present in header childs`() {
|
||||
@Test
|
||||
fun `should return null when title block is not present in header childs`() {
|
||||
|
||||
val root = MockDataFactory.randomUuid()
|
||||
|
||||
|
@ -982,10 +982,12 @@ class BlockExtensionTest {
|
|||
val document = listOf(page, header, a)
|
||||
|
||||
val result = document.title()
|
||||
|
||||
assertNull(result)
|
||||
}
|
||||
|
||||
@Test(expected = NoSuchElementException::class)
|
||||
fun `should throw NoSuchElementException when header is not present`() {
|
||||
@Test
|
||||
fun `should return null when header is not present`() {
|
||||
|
||||
val root = MockDataFactory.randomUuid()
|
||||
|
||||
|
@ -1010,5 +1012,7 @@ class BlockExtensionTest {
|
|||
val document = listOf(page, a)
|
||||
|
||||
val result = document.title()
|
||||
|
||||
assertNull(result)
|
||||
}
|
||||
}
|
|
@ -23,8 +23,8 @@ class BlockMiddleware(
|
|||
}
|
||||
|
||||
override suspend fun createPage(
|
||||
ctx: Id?, emoji: String?, isDraft: Boolean?
|
||||
): String = middleware.createPage(ctx = ctx, emoji = emoji, isDraft = isDraft)
|
||||
ctx: Id?, emoji: String?, isDraft: Boolean?, type: String?
|
||||
): String = middleware.createPage(ctx = ctx, emoji = emoji, isDraft = isDraft, type = type)
|
||||
|
||||
override suspend fun createPage(command: Command.CreateNewDocument): String =
|
||||
middleware.createPage(command)
|
||||
|
|
|
@ -183,11 +183,12 @@ class Middleware(
|
|||
}
|
||||
|
||||
@Throws(Exception::class)
|
||||
fun createPage(ctx: Id?, emoji: String?, isDraft: Boolean?): Id {
|
||||
fun createPage(ctx: Id?, emoji: String?, isDraft: Boolean?, type: String?): Id {
|
||||
|
||||
val details: MutableMap<String, Any> = mutableMapOf()
|
||||
emoji?.let { details[iconEmojiKey] = it}
|
||||
isDraft?.let { details[isDraftKey] = it }
|
||||
type?.let { details[typeKey] = it }
|
||||
|
||||
val request = Rpc.Block.CreatePage.Request(
|
||||
contextId = ctx.orEmpty(),
|
||||
|
|
|
@ -5,6 +5,8 @@ import androidx.lifecycle.viewModelScope
|
|||
import com.anytypeio.anytype.analytics.base.Analytics
|
||||
import com.anytypeio.anytype.analytics.base.EventsDictionary
|
||||
import com.anytypeio.anytype.analytics.base.EventsDictionary.PAGE_CREATE
|
||||
import com.anytypeio.anytype.analytics.base.EventsDictionary.PROP_IS_DRAFT
|
||||
import com.anytypeio.anytype.analytics.base.EventsDictionary.PROP_TYPE
|
||||
import com.anytypeio.anytype.analytics.base.EventsDictionary.SCREEN_DASHBOARD
|
||||
import com.anytypeio.anytype.analytics.base.EventsDictionary.SCREEN_PROFILE
|
||||
import com.anytypeio.anytype.analytics.base.EventsDictionary.TAB_ARCHIVE
|
||||
|
@ -27,6 +29,7 @@ import com.anytypeio.anytype.domain.dashboard.interactor.CloseDashboard
|
|||
import com.anytypeio.anytype.domain.dashboard.interactor.OpenDashboard
|
||||
import com.anytypeio.anytype.domain.dataview.interactor.SearchObjects
|
||||
import com.anytypeio.anytype.domain.event.interactor.InterceptEvents
|
||||
import com.anytypeio.anytype.domain.launch.GetDefaultEditorType
|
||||
import com.anytypeio.anytype.domain.misc.UrlBuilder
|
||||
import com.anytypeio.anytype.domain.objects.DeleteObjects
|
||||
import com.anytypeio.anytype.domain.objects.SetObjectListIsArchived
|
||||
|
@ -58,6 +61,7 @@ class HomeDashboardViewModel(
|
|||
private val getDebugSettings: GetDebugSettings,
|
||||
private val analytics: Analytics,
|
||||
private val searchObjects: SearchObjects,
|
||||
private val getDefaultEditorType: GetDefaultEditorType,
|
||||
private val urlBuilder: UrlBuilder,
|
||||
private val setObjectListIsArchived: SetObjectListIsArchived,
|
||||
private val deleteObjects: DeleteObjects
|
||||
|
@ -181,25 +185,7 @@ class HomeDashboardViewModel(
|
|||
}
|
||||
|
||||
fun onAddNewDocumentClicked() {
|
||||
val startTime = System.currentTimeMillis()
|
||||
createPage.invoke(viewModelScope, CreatePage.Params(ctx = null, isDraft = true)) { result ->
|
||||
result.either(
|
||||
fnL = { e -> Timber.e(e, "Error while creating a new page") },
|
||||
fnR = { id ->
|
||||
val middle = System.currentTimeMillis()
|
||||
viewModelScope.sendEvent(
|
||||
analytics = analytics,
|
||||
startTime = startTime,
|
||||
middleTime = middle,
|
||||
renderTime = middle,
|
||||
eventName = PAGE_CREATE,
|
||||
props = Props.empty()
|
||||
)
|
||||
machine.onEvents(listOf(Machine.Event.OnFinishedCreatingPage))
|
||||
proceedWithOpeningDocument(id)
|
||||
}
|
||||
)
|
||||
}
|
||||
proceedWithGettingDefaultPageType()
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -652,12 +638,54 @@ class HomeDashboardViewModel(
|
|||
ObjectType.Layout.PROFILE,
|
||||
ObjectType.Layout.FILE,
|
||||
ObjectType.Layout.IMAGE,
|
||||
ObjectType.Layout.SET
|
||||
ObjectType.Layout.SET,
|
||||
ObjectType.Layout.NOTE
|
||||
)
|
||||
}
|
||||
|
||||
enum class TAB { FAVOURITE, RECENT, INBOX, SETS, ARCHIVE }
|
||||
|
||||
//region CREATE PAGE
|
||||
private fun proceedWithGettingDefaultPageType() {
|
||||
viewModelScope.launch {
|
||||
getDefaultEditorType.invoke(Unit).proceed(
|
||||
failure = { Timber.e(it, "Error while getting default page type") },
|
||||
success = { response -> proceedWithCreatePage(type = response.type) }
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
private suspend fun proceedWithCreatePage(type: String?) {
|
||||
val startTime = System.currentTimeMillis()
|
||||
val isDraft = true
|
||||
val params = CreatePage.Params(
|
||||
ctx = null,
|
||||
isDraft = isDraft,
|
||||
type = type,
|
||||
emoji = null
|
||||
)
|
||||
createPage.invoke(viewModelScope, params) { result ->
|
||||
result.either(
|
||||
fnL = { e -> Timber.e(e, "Error while creating a new page") },
|
||||
fnR = { id ->
|
||||
val middle = System.currentTimeMillis()
|
||||
val props = Props(mapOf(PROP_TYPE to type, PROP_IS_DRAFT to isDraft))
|
||||
viewModelScope.sendEvent(
|
||||
analytics = analytics,
|
||||
startTime = startTime,
|
||||
middleTime = middle,
|
||||
renderTime = middle,
|
||||
eventName = PAGE_CREATE,
|
||||
props = props
|
||||
)
|
||||
machine.onEvents(listOf(Machine.Event.OnFinishedCreatingPage))
|
||||
proceedWithOpeningDocument(id)
|
||||
}
|
||||
)
|
||||
}
|
||||
}
|
||||
//endregion
|
||||
|
||||
enum class Mode { DEFAULT, SELECTION }
|
||||
|
||||
sealed class Alert {
|
||||
|
|
|
@ -10,6 +10,7 @@ import com.anytypeio.anytype.domain.config.GetDebugSettings
|
|||
import com.anytypeio.anytype.domain.dashboard.interactor.*
|
||||
import com.anytypeio.anytype.domain.dataview.interactor.SearchObjects
|
||||
import com.anytypeio.anytype.domain.event.interactor.InterceptEvents
|
||||
import com.anytypeio.anytype.domain.launch.GetDefaultEditorType
|
||||
import com.anytypeio.anytype.domain.misc.UrlBuilder
|
||||
import com.anytypeio.anytype.domain.objects.DeleteObjects
|
||||
import com.anytypeio.anytype.domain.objects.SetObjectListIsArchived
|
||||
|
@ -27,6 +28,7 @@ class HomeDashboardViewModelFactory(
|
|||
private val getDebugSettings: GetDebugSettings,
|
||||
private val analytics: Analytics,
|
||||
private val searchObjects: SearchObjects,
|
||||
private val getDefaultEditorType: GetDefaultEditorType,
|
||||
private val urlBuilder: UrlBuilder,
|
||||
private val setObjectListIsArchived: SetObjectListIsArchived,
|
||||
private val deleteObjects: DeleteObjects
|
||||
|
@ -47,6 +49,7 @@ class HomeDashboardViewModelFactory(
|
|||
analytics = analytics,
|
||||
searchObjects = searchObjects,
|
||||
urlBuilder = urlBuilder,
|
||||
getDefaultEditorType = getDefaultEditorType,
|
||||
deleteObjects = deleteObjects,
|
||||
setObjectListIsArchived = setObjectListIsArchived
|
||||
) as T
|
||||
|
|
|
@ -33,7 +33,6 @@ interface Editor {
|
|||
val objectTypes: Store.ObjectTypes = Store.ObjectTypes()
|
||||
val textSelection: Store<Editor.TextSelection> = Store.TextSelection()
|
||||
val objectRestrictions: Store.ObjectRestrictions = Store.ObjectRestrictions()
|
||||
val objectIsDraft: Store.ObjectIsDraft = Store.ObjectIsDraft()
|
||||
}
|
||||
|
||||
class Proxer(
|
||||
|
|
|
@ -43,6 +43,7 @@ import com.anytypeio.anytype.domain.dataview.interactor.SearchObjects
|
|||
import com.anytypeio.anytype.domain.editor.Editor
|
||||
import com.anytypeio.anytype.domain.error.Error
|
||||
import com.anytypeio.anytype.domain.event.interactor.InterceptEvents
|
||||
import com.anytypeio.anytype.domain.launch.GetDefaultEditorType
|
||||
import com.anytypeio.anytype.domain.misc.UrlBuilder
|
||||
import com.anytypeio.anytype.domain.objects.SetObjectIsArchived
|
||||
import com.anytypeio.anytype.domain.page.*
|
||||
|
@ -135,6 +136,7 @@ class EditorViewModel(
|
|||
private val getCompatibleObjectTypes: GetCompatibleObjectTypes,
|
||||
private val objectTypesProvider: ObjectTypesProvider,
|
||||
private val searchObjects: SearchObjects,
|
||||
private val getDefaultEditorType: GetDefaultEditorType
|
||||
) : ViewStateViewModel<ViewState>(),
|
||||
SupportNavigation<EventWrapper<AppNavigation.Command>>,
|
||||
SupportCommand<Command>,
|
||||
|
@ -285,8 +287,8 @@ class EditorViewModel(
|
|||
orchestrator.stores.relations.update(event.relations)
|
||||
orchestrator.stores.objectTypes.update(event.objectTypes)
|
||||
orchestrator.stores.objectRestrictions.update(event.objectRestrictions)
|
||||
orchestrator.stores.objectIsDraft.set(event.details, context)
|
||||
showObjectTypesWidget()
|
||||
val objectType = event.details.details[context]?.type?.firstOrNull()
|
||||
proceedWithShowingObjectTypesWidget(objectType, event.blocks)
|
||||
}
|
||||
if (event is Event.Command.Details) {
|
||||
orchestrator.stores.details.apply { update(current().process(event)) }
|
||||
|
@ -604,6 +606,7 @@ class EditorViewModel(
|
|||
}
|
||||
}
|
||||
|
||||
//TODO need refactoring, logic must depend on Object Layouts
|
||||
private fun onStartFocusing(payload: Payload) {
|
||||
val event = payload.events.find { it is Event.Command.ShowObject }
|
||||
if (event is Event.Command.ShowObject) {
|
||||
|
@ -616,17 +619,27 @@ class EditorViewModel(
|
|||
if (content is Content.Layout && content.type == Content.Layout.Type.HEADER) {
|
||||
try {
|
||||
val title = event.blocks.title()
|
||||
if (title.content<Content.Text>().text.isEmpty()) {
|
||||
if (title != null && title.content<Content.Text>().text.isEmpty()) {
|
||||
val focus = Editor.Focus(id = title.id, cursor = Editor.Cursor.End)
|
||||
viewModelScope.launch { orchestrator.stores.focus.update(focus) }
|
||||
} else {
|
||||
Timber.d("Skipping initial focusing. Title is not empty.")
|
||||
Timber.d("Skipping initial focusing. Title is not empty or is null")
|
||||
}
|
||||
} catch (e: Throwable) {
|
||||
Timber.e(e, "Error while initial focusing")
|
||||
}
|
||||
}
|
||||
}
|
||||
root.children.size == 2 -> {
|
||||
val layout = event.details.details[root.id]?.layout
|
||||
if (layout == ObjectType.Layout.NOTE.code.toDouble()) {
|
||||
val block = event.blocks.firstOrNull { it.content is Content.Text }
|
||||
if (block != null && block.content<Content.Text>().text.isEmpty()) {
|
||||
val focus = Editor.Focus(id = block.id, cursor = Editor.Cursor.End)
|
||||
viewModelScope.launch { orchestrator.stores.focus.update(focus) }
|
||||
}
|
||||
}
|
||||
}
|
||||
else -> Timber.d("Skipping initial focusing, document is not empty.")
|
||||
}
|
||||
}
|
||||
|
@ -782,7 +795,6 @@ class EditorViewModel(
|
|||
)
|
||||
viewModelScope.launch { orchestrator.stores.views.update(new) }
|
||||
viewModelScope.launch { orchestrator.proxies.changes.send(update) }
|
||||
viewModelScope.launch { checkObjectIsDraft() }
|
||||
}
|
||||
|
||||
fun onDescriptionBlockTextChanged(view: BlockView.Description) {
|
||||
|
@ -819,6 +831,7 @@ class EditorViewModel(
|
|||
|
||||
viewModelScope.launch { store.update(new) }
|
||||
viewModelScope.launch { orchestrator.proxies.changes.send(update) }
|
||||
if (isObjectTypesWidgetVisible) hideObjectTypesWidget()
|
||||
}
|
||||
|
||||
fun onSelectionChanged(id: String, selection: IntRange) {
|
||||
|
@ -3476,31 +3489,6 @@ class EditorViewModel(
|
|||
}
|
||||
}
|
||||
|
||||
fun onPlusButtonPressed() {
|
||||
Timber.d("onPlusButtonPressed, ")
|
||||
val startTime = System.currentTimeMillis()
|
||||
createPage(
|
||||
scope = viewModelScope,
|
||||
params = CreatePage.Params(ctx = null, isDraft = true)
|
||||
) { result ->
|
||||
result.either(
|
||||
fnL = { Timber.e(it, "Error while creating a new page on home dashboard") },
|
||||
fnR = { id ->
|
||||
val middle = System.currentTimeMillis()
|
||||
viewModelScope.sendEvent(
|
||||
analytics = analytics,
|
||||
startTime = startTime,
|
||||
middleTime = middle,
|
||||
renderTime = middle,
|
||||
eventName = PAGE_CREATE,
|
||||
props = Props.empty()
|
||||
)
|
||||
proceedWithOpeningPage(id)
|
||||
}
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
fun onProceedWithFilePath(filePath: String?) {
|
||||
Timber.d("onProceedWithFilePath, filePath:[$filePath]")
|
||||
if (filePath == null) {
|
||||
|
@ -4646,6 +4634,7 @@ class EditorViewModel(
|
|||
Timber.d("onKeyPressedEvent, event:[$event]")
|
||||
when (event) {
|
||||
is KeyPressedEvent.OnTitleBlockEnterKeyEvent -> {
|
||||
if (isObjectTypesWidgetVisible) hideObjectTypesWidget()
|
||||
proceedWithTitleEnterClicked(
|
||||
title = event.target,
|
||||
text = event.text,
|
||||
|
@ -5146,6 +5135,9 @@ class EditorViewModel(
|
|||
//endregion
|
||||
|
||||
//region OBJECT TYPES WIDGET
|
||||
private val isObjectTypesWidgetVisible : Boolean get() =
|
||||
controlPanelViewState.value?.objectTypesToolbar?.isVisible ?: false
|
||||
|
||||
fun onObjectTypesWidgetItemClicked(id: Id) {
|
||||
Timber.d("onObjectTypesWidgetItemClicked, id:[$id]")
|
||||
controlPanelInteractor.onEvent(
|
||||
|
@ -5175,42 +5167,57 @@ class EditorViewModel(
|
|||
)
|
||||
}
|
||||
|
||||
private fun showObjectTypesWidget() {
|
||||
private fun proceedWithShowingObjectTypesWidget(objectType: String?, blocks: List<Block>) {
|
||||
val restrictions = orchestrator.stores.objectRestrictions.current()
|
||||
if (restrictions.contains(ObjectRestriction.TYPE_CHANGE)) {
|
||||
_toasts.offer(NOT_ALLOWED_FOR_OBJECT)
|
||||
Timber.d("No interaction allowed with this object type")
|
||||
return
|
||||
}
|
||||
val isDraft = orchestrator.stores.objectIsDraft.current()
|
||||
if (isDraft) {
|
||||
val smartBlockType = getObjectSmartBlockType()
|
||||
viewModelScope.launch {
|
||||
getCompatibleObjectTypes.invoke(
|
||||
GetCompatibleObjectTypes.Params(smartBlockType)
|
||||
).proceed(
|
||||
failure = { Timber.e(it, "Error while getting object types") },
|
||||
success = { objectTypes ->
|
||||
val views = listOf(ObjectTypeView.Search()) + objectTypes.toObjectTypeView()
|
||||
controlPanelInteractor.onEvent(
|
||||
ControlPanelMachine.Event.ObjectTypesWidgetEvent.Show(views)
|
||||
)
|
||||
when (objectType) {
|
||||
ObjectType.NOTE_URL -> {
|
||||
val root = blocks.find { it.id == context } ?: return
|
||||
if (root.children.size == 2) {
|
||||
val lastBlock = blocks.find { it.id == root.children.last() }
|
||||
if (lastBlock != null && lastBlock.content is Content.Text) {
|
||||
if (lastBlock.content<Content.Text>().text.isEmpty()) {
|
||||
proceedWithGettingObjectTypesForObjectTypeWidget()
|
||||
}
|
||||
}
|
||||
)
|
||||
}
|
||||
}
|
||||
else -> {
|
||||
val root = blocks.find { it.id == context } ?: return
|
||||
if (root.children.size == 1) {
|
||||
val title = blocks.title() ?: return
|
||||
if (title.content<Content.Text>().text.isEmpty()) {
|
||||
proceedWithGettingObjectTypesForObjectTypeWidget()
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private suspend fun checkObjectIsDraft() {
|
||||
val isDraft = orchestrator.stores.objectIsDraft.current()
|
||||
if (isDraft) {
|
||||
orchestrator.stores.objectIsDraft.set(state = false)
|
||||
controlPanelInteractor.onEvent(
|
||||
ControlPanelMachine.Event.ObjectTypesWidgetEvent.Hide
|
||||
private fun proceedWithGettingObjectTypesForObjectTypeWidget() {
|
||||
val smartBlockType = getObjectSmartBlockType()
|
||||
val params = GetCompatibleObjectTypes.Params(smartBlockType)
|
||||
viewModelScope.launch {
|
||||
getCompatibleObjectTypes.invoke(params).proceed(
|
||||
failure = { Timber.e(it, "Error while getting object types") },
|
||||
success = { objectTypes ->
|
||||
val views = listOf(ObjectTypeView.Search()) + objectTypes.toObjectTypeView()
|
||||
controlPanelInteractor.onEvent(
|
||||
ControlPanelMachine.Event.ObjectTypesWidgetEvent.Show(views)
|
||||
)
|
||||
}
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
private fun hideObjectTypesWidget() {
|
||||
controlPanelInteractor.onEvent(ControlPanelMachine.Event.ObjectTypesWidgetEvent.Hide)
|
||||
}
|
||||
|
||||
private fun getObjectSmartBlockType(): SmartBlockType {
|
||||
val block = blocks.firstOrNull { it.id == context }
|
||||
return if (block?.content is Content.Smart) {
|
||||
|
|
|
@ -13,6 +13,7 @@ import com.anytypeio.anytype.domain.block.interactor.UpdateLinkMarks
|
|||
import com.anytypeio.anytype.domain.dataview.interactor.GetCompatibleObjectTypes
|
||||
import com.anytypeio.anytype.domain.dataview.interactor.SearchObjects
|
||||
import com.anytypeio.anytype.domain.event.interactor.InterceptEvents
|
||||
import com.anytypeio.anytype.domain.launch.GetDefaultEditorType
|
||||
import com.anytypeio.anytype.domain.misc.UrlBuilder
|
||||
import com.anytypeio.anytype.domain.objects.SetObjectIsArchived
|
||||
import com.anytypeio.anytype.domain.page.*
|
||||
|
@ -45,7 +46,8 @@ open class EditorViewModelFactory(
|
|||
private val updateDetail: UpdateDetail,
|
||||
private val getCompatibleObjectTypes: GetCompatibleObjectTypes,
|
||||
private val objectTypesProvider: ObjectTypesProvider,
|
||||
private val searchObjects: SearchObjects
|
||||
private val searchObjects: SearchObjects,
|
||||
private val getDefaultEditorType: GetDefaultEditorType
|
||||
) : ViewModelProvider.Factory {
|
||||
|
||||
@Suppress("UNCHECKED_CAST")
|
||||
|
@ -72,7 +74,8 @@ open class EditorViewModelFactory(
|
|||
updateDetail = updateDetail,
|
||||
getCompatibleObjectTypes = getCompatibleObjectTypes,
|
||||
objectTypesProvider = objectTypesProvider,
|
||||
searchObjects = searchObjects
|
||||
searchObjects = searchObjects,
|
||||
getDefaultEditorType = getDefaultEditorType
|
||||
) as T
|
||||
}
|
||||
}
|
|
@ -76,14 +76,5 @@ interface Store<T> {
|
|||
class Relations : State<List<Relation>>(emptyList())
|
||||
class ObjectTypes : State<List<ObjectType>>(emptyList())
|
||||
class ObjectRestrictions : State<List<ObjectRestriction>>(emptyList())
|
||||
class ObjectIsDraft : State<Boolean>(false) {
|
||||
suspend fun set(state: Boolean) {
|
||||
super.update(state)
|
||||
}
|
||||
suspend fun set(details: Block.Details, ctx: Id) {
|
||||
val isDraft = details.details[ctx]?.isDraft ?: false
|
||||
super.update(isDraft)
|
||||
}
|
||||
}
|
||||
class TextSelection : State<Editor.TextSelection>(Editor.TextSelection.empty())
|
||||
}
|
|
@ -24,6 +24,7 @@ import com.anytypeio.anytype.presentation.editor.editor.model.Types.HOLDER_HEADE
|
|||
import com.anytypeio.anytype.presentation.editor.editor.model.Types.HOLDER_HEADER_THREE
|
||||
import com.anytypeio.anytype.presentation.editor.editor.model.Types.HOLDER_HEADER_TWO
|
||||
import com.anytypeio.anytype.presentation.editor.editor.model.Types.HOLDER_HIGHLIGHT
|
||||
import com.anytypeio.anytype.presentation.editor.editor.model.Types.HOLDER_NOTE_TITLE
|
||||
import com.anytypeio.anytype.presentation.editor.editor.model.Types.HOLDER_NUMBERED
|
||||
import com.anytypeio.anytype.presentation.editor.editor.model.Types.HOLDER_OBJECT_TYPE
|
||||
import com.anytypeio.anytype.presentation.editor.editor.model.Types.HOLDER_PAGE
|
||||
|
@ -540,7 +541,24 @@ sealed class BlockView : ViewType, Parcelable {
|
|||
) : Title() {
|
||||
override fun getViewType() = HOLDER_ARCHIVE_TITLE
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* UI-model for a note-layout title block.
|
||||
* In fact it's just an empty space, because NOTE LAYOUT doesn't have title
|
||||
* @property id block's id
|
||||
*/
|
||||
@Parcelize
|
||||
data class TitleNote(
|
||||
override val id: String
|
||||
) : BlockView() {
|
||||
override fun getViewType() = HOLDER_NOTE_TITLE
|
||||
|
||||
companion object {
|
||||
const val INTERNAL_ID = "HOLDER_NOTE_TITLE"
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
|
@ -6,6 +6,7 @@ object Types {
|
|||
const val HOLDER_PROFILE_TITLE = 35
|
||||
const val HOLDER_ARCHIVE_TITLE = 36
|
||||
const val HOLDER_TODO_TITLE = 48
|
||||
const val HOLDER_NOTE_TITLE = 50
|
||||
const val HOLDER_HEADER_ONE = 2
|
||||
const val HOLDER_HEADER_TWO = 3
|
||||
const val HOLDER_HEADER_THREE = 4
|
||||
|
|
|
@ -53,6 +53,9 @@ class DefaultBlockViewRenderer(
|
|||
)
|
||||
)
|
||||
}
|
||||
if (isLayoutNote(root, details)) {
|
||||
result.add(BlockView.TitleNote(id = BlockView.TitleNote.INTERNAL_ID))
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -472,6 +475,7 @@ class DefaultBlockViewRenderer(
|
|||
relations = relations,
|
||||
details = details
|
||||
)
|
||||
|
||||
if (featured.relations.isNotEmpty()) {
|
||||
result.add(featured)
|
||||
}
|
||||
|
@ -1350,4 +1354,9 @@ class DefaultBlockViewRenderer(
|
|||
is Cursor.Range -> cursor.range.first
|
||||
}
|
||||
}
|
||||
|
||||
private fun isLayoutNote(root: Block, details: Block.Details): Boolean {
|
||||
val layoutCode = details.details[root.id]?.layout?.toInt()
|
||||
return layoutCode == ObjectType.Layout.NOTE.code
|
||||
}
|
||||
}
|
|
@ -112,8 +112,8 @@ fun ObjectSet.render(
|
|||
fun ObjectSet.title(
|
||||
ctx: Id,
|
||||
urlBuilder: UrlBuilder
|
||||
): BlockView.Title.Basic {
|
||||
val title = blocks.title()
|
||||
): BlockView.Title.Basic? {
|
||||
val title = blocks.title() ?: return null
|
||||
|
||||
val objectDetails = details[ctx]
|
||||
|
||||
|
|
|
@ -4,6 +4,6 @@ import com.anytypeio.anytype.presentation.editor.editor.model.BlockView
|
|||
import com.anytypeio.anytype.presentation.sets.model.Viewer
|
||||
|
||||
data class ObjectSetViewState(
|
||||
val title: BlockView.Title.Basic,
|
||||
val title: BlockView.Title.Basic?,
|
||||
val viewer: Viewer
|
||||
)
|
|
@ -5,15 +5,15 @@ import androidx.lifecycle.ViewModelProvider
|
|||
import androidx.lifecycle.viewModelScope
|
||||
import com.anytypeio.anytype.analytics.base.Analytics
|
||||
import com.anytypeio.anytype.core_models.ObjectType
|
||||
import com.anytypeio.anytype.domain.launch.GetDefaultPageType
|
||||
import com.anytypeio.anytype.domain.launch.SetDefaultPageType
|
||||
import com.anytypeio.anytype.domain.launch.GetDefaultEditorType
|
||||
import com.anytypeio.anytype.domain.launch.SetDefaultEditorType
|
||||
import kotlinx.coroutines.flow.MutableSharedFlow
|
||||
import kotlinx.coroutines.launch
|
||||
import timber.log.Timber
|
||||
|
||||
class UserSettingsViewModel(
|
||||
private val getDefaultPageType: GetDefaultPageType,
|
||||
private val setDefaultPageType: SetDefaultPageType,
|
||||
private val getDefaultEditorType: GetDefaultEditorType,
|
||||
private val setDefaultEditorType: SetDefaultEditorType,
|
||||
private val analytics: Analytics
|
||||
) : ViewModel() {
|
||||
|
||||
|
@ -21,7 +21,7 @@ class UserSettingsViewModel(
|
|||
|
||||
init {
|
||||
viewModelScope.launch {
|
||||
getDefaultPageType.invoke(Unit).proceed(
|
||||
getDefaultEditorType.invoke(Unit).proceed(
|
||||
failure = { Timber.e(it, "Error while getting user settings") },
|
||||
success = { response ->
|
||||
if (response.type == ObjectType.NOTE_URL) {
|
||||
|
@ -44,7 +44,7 @@ class UserSettingsViewModel(
|
|||
|
||||
private fun proceedWithUpdateType(type: String) {
|
||||
viewModelScope.launch {
|
||||
setDefaultPageType.invoke(SetDefaultPageType.Params(type)).process(
|
||||
setDefaultEditorType.invoke(SetDefaultEditorType.Params(type)).process(
|
||||
failure = {
|
||||
Timber.e(it, "Error while setting default object type")
|
||||
commands.emit(Command.Exit)
|
||||
|
@ -62,16 +62,16 @@ class UserSettingsViewModel(
|
|||
}
|
||||
|
||||
class Factory(
|
||||
private val getDefaultPageType: GetDefaultPageType,
|
||||
private val setDefaultPageType: SetDefaultPageType,
|
||||
private val getDefaultEditorType: GetDefaultEditorType,
|
||||
private val setDefaultEditorType: SetDefaultEditorType,
|
||||
private val analytics: Analytics
|
||||
) : ViewModelProvider.Factory {
|
||||
@Suppress("UNCHECKED_CAST")
|
||||
override fun <T : ViewModel?> create(
|
||||
modelClass: Class<T>
|
||||
): T = UserSettingsViewModel(
|
||||
getDefaultPageType = getDefaultPageType,
|
||||
setDefaultPageType = setDefaultPageType,
|
||||
getDefaultEditorType = getDefaultEditorType,
|
||||
setDefaultEditorType = setDefaultEditorType,
|
||||
analytics = analytics
|
||||
) as T
|
||||
}
|
||||
|
|
|
@ -21,8 +21,8 @@ import com.anytypeio.anytype.domain.auth.interactor.LaunchWallet
|
|||
import com.anytypeio.anytype.domain.auth.model.AuthStatus
|
||||
import com.anytypeio.anytype.domain.base.BaseUseCase
|
||||
import com.anytypeio.anytype.domain.block.interactor.sets.StoreObjectTypes
|
||||
import com.anytypeio.anytype.domain.launch.GetDefaultPageType
|
||||
import com.anytypeio.anytype.domain.launch.SetDefaultPageType
|
||||
import com.anytypeio.anytype.domain.launch.GetDefaultEditorType
|
||||
import com.anytypeio.anytype.domain.launch.SetDefaultEditorType
|
||||
import com.anytypeio.anytype.presentation.objects.SupportedLayouts
|
||||
import kotlinx.coroutines.flow.MutableSharedFlow
|
||||
import kotlinx.coroutines.launch
|
||||
|
@ -40,8 +40,8 @@ class SplashViewModel(
|
|||
private val launchAccount: LaunchAccount,
|
||||
private val storeObjectTypes: StoreObjectTypes,
|
||||
private val getLastOpenedObject: GetLastOpenedObject,
|
||||
private val getDefaultPageType: GetDefaultPageType,
|
||||
private val setDefaultPageType: SetDefaultPageType
|
||||
private val getDefaultEditorType: GetDefaultEditorType,
|
||||
private val setDefaultEditorType: SetDefaultEditorType
|
||||
) : ViewModel() {
|
||||
|
||||
val commands = MutableSharedFlow<Command>(replay = 0)
|
||||
|
@ -52,7 +52,7 @@ class SplashViewModel(
|
|||
|
||||
private fun proceedWithUserSettings() {
|
||||
viewModelScope.launch {
|
||||
getDefaultPageType.invoke(Unit).process(
|
||||
getDefaultEditorType.invoke(Unit).process(
|
||||
failure = {
|
||||
Timber.e(it, "Error while getting default page type")
|
||||
checkAuthorizationStatus()
|
||||
|
@ -77,9 +77,9 @@ class SplashViewModel(
|
|||
DEFAULT_TYPE_UPDATE
|
||||
}
|
||||
viewModelScope.launch {
|
||||
val params = SetDefaultPageType.Params(defaultType)
|
||||
val params = SetDefaultEditorType.Params(defaultType)
|
||||
Timber.d("Start to update Default Page Type:${params.type}")
|
||||
setDefaultPageType.invoke(params).process(
|
||||
setDefaultEditorType.invoke(params).process(
|
||||
failure = {
|
||||
Timber.e(it, "Error while setting default page type")
|
||||
checkAuthorizationStatus()
|
||||
|
|
|
@ -8,8 +8,8 @@ import com.anytypeio.anytype.domain.auth.interactor.GetLastOpenedObject
|
|||
import com.anytypeio.anytype.domain.auth.interactor.LaunchAccount
|
||||
import com.anytypeio.anytype.domain.auth.interactor.LaunchWallet
|
||||
import com.anytypeio.anytype.domain.block.interactor.sets.StoreObjectTypes
|
||||
import com.anytypeio.anytype.domain.launch.GetDefaultPageType
|
||||
import com.anytypeio.anytype.domain.launch.SetDefaultPageType
|
||||
import com.anytypeio.anytype.domain.launch.GetDefaultEditorType
|
||||
import com.anytypeio.anytype.domain.launch.SetDefaultEditorType
|
||||
|
||||
/**
|
||||
* Created by Konstantin Ivanov
|
||||
|
@ -23,8 +23,8 @@ class SplashViewModelFactory(
|
|||
private val analytics: Analytics,
|
||||
private val storeObjectTypes: StoreObjectTypes,
|
||||
private val getLastOpenedObject: GetLastOpenedObject,
|
||||
private val getDefaultPageType: GetDefaultPageType,
|
||||
private val setDefaultPageType: SetDefaultPageType
|
||||
private val getDefaultEditorType: GetDefaultEditorType,
|
||||
private val setDefaultEditorType: SetDefaultEditorType
|
||||
) : ViewModelProvider.Factory {
|
||||
|
||||
@Suppress("UNCHECKED_CAST")
|
||||
|
@ -36,7 +36,7 @@ class SplashViewModelFactory(
|
|||
analytics = analytics,
|
||||
storeObjectTypes = storeObjectTypes,
|
||||
getLastOpenedObject = getLastOpenedObject,
|
||||
getDefaultPageType = getDefaultPageType,
|
||||
setDefaultPageType = setDefaultPageType
|
||||
getDefaultEditorType = getDefaultEditorType,
|
||||
setDefaultEditorType = setDefaultEditorType
|
||||
) as T
|
||||
}
|
|
@ -18,6 +18,7 @@ import com.anytypeio.anytype.domain.config.GetDebugSettings
|
|||
import com.anytypeio.anytype.domain.dashboard.interactor.*
|
||||
import com.anytypeio.anytype.domain.dataview.interactor.SearchObjects
|
||||
import com.anytypeio.anytype.domain.event.interactor.InterceptEvents
|
||||
import com.anytypeio.anytype.domain.launch.GetDefaultEditorType
|
||||
import com.anytypeio.anytype.domain.misc.UrlBuilder
|
||||
import com.anytypeio.anytype.domain.objects.DeleteObjects
|
||||
import com.anytypeio.anytype.domain.objects.SetObjectListIsArchived
|
||||
|
@ -82,6 +83,9 @@ open class DashboardTestSetup {
|
|||
@Mock
|
||||
lateinit var objectTypesProvider: ObjectTypesProvider
|
||||
|
||||
@Mock
|
||||
lateinit var getDefaultEditorType: GetDefaultEditorType
|
||||
|
||||
lateinit var vm: HomeDashboardViewModel
|
||||
|
||||
val builder: UrlBuilder get() = UrlBuilder(gateway)
|
||||
|
@ -108,6 +112,7 @@ open class DashboardTestSetup {
|
|||
analytics = analytics,
|
||||
searchObjects = searchObjects,
|
||||
urlBuilder = builder,
|
||||
getDefaultEditorType = getDefaultEditorType,
|
||||
setObjectListIsArchived = setObjectListIsArchived,
|
||||
deleteObjects = deleteObjects
|
||||
)
|
||||
|
|
|
@ -16,6 +16,7 @@ import com.anytypeio.anytype.domain.config.GetDebugSettings
|
|||
import com.anytypeio.anytype.domain.dashboard.interactor.*
|
||||
import com.anytypeio.anytype.domain.dataview.interactor.SearchObjects
|
||||
import com.anytypeio.anytype.domain.event.interactor.InterceptEvents
|
||||
import com.anytypeio.anytype.domain.launch.GetDefaultEditorType
|
||||
import com.anytypeio.anytype.domain.misc.UrlBuilder
|
||||
import com.anytypeio.anytype.domain.objects.DeleteObjects
|
||||
import com.anytypeio.anytype.domain.objects.SetObjectListIsArchived
|
||||
|
@ -83,6 +84,9 @@ class HomeDashboardViewModelTest {
|
|||
@Mock
|
||||
lateinit var objectTypesProvider: ObjectTypesProvider
|
||||
|
||||
@Mock
|
||||
lateinit var getDefaultEditorType: GetDefaultEditorType
|
||||
|
||||
private lateinit var vm: HomeDashboardViewModel
|
||||
|
||||
private val config = Config(
|
||||
|
@ -116,7 +120,8 @@ class HomeDashboardViewModelTest {
|
|||
searchObjects = searchObjects,
|
||||
deleteObjects = deleteObjects,
|
||||
setObjectListIsArchived = setObjectListIsArchived,
|
||||
urlBuilder = builder
|
||||
urlBuilder = builder,
|
||||
getDefaultEditorType = getDefaultEditorType
|
||||
)
|
||||
}
|
||||
|
||||
|
@ -305,6 +310,7 @@ class HomeDashboardViewModelTest {
|
|||
fun `should start creating page when requested from UI`() {
|
||||
|
||||
stubObserveEvents()
|
||||
stubGetDefaultObjectType(null)
|
||||
|
||||
vm = buildViewModel()
|
||||
|
||||
|
@ -322,6 +328,7 @@ class HomeDashboardViewModelTest {
|
|||
stubGetEditorSettings()
|
||||
stubCloseDashboard()
|
||||
stubCreatePage(id)
|
||||
stubGetDefaultObjectType(null)
|
||||
|
||||
vm = buildViewModel()
|
||||
|
||||
|
@ -384,4 +391,10 @@ class HomeDashboardViewModelTest {
|
|||
onBlocking { invoke(any()) } doReturn Either.Right(DebugSettings(true))
|
||||
}
|
||||
}
|
||||
|
||||
private fun stubGetDefaultObjectType(type: String?) {
|
||||
getDefaultEditorType.stub {
|
||||
onBlocking { invoke(Unit) } doReturn Either.Right(GetDefaultEditorType.Response(type))
|
||||
}
|
||||
}
|
||||
}
|
|
@ -21,6 +21,7 @@ import com.anytypeio.anytype.domain.dataview.interactor.SearchObjects
|
|||
import com.anytypeio.anytype.domain.dataview.interactor.SetRelationKey
|
||||
import com.anytypeio.anytype.domain.download.DownloadFile
|
||||
import com.anytypeio.anytype.domain.event.interactor.InterceptEvents
|
||||
import com.anytypeio.anytype.domain.launch.GetDefaultEditorType
|
||||
import com.anytypeio.anytype.domain.misc.UrlBuilder
|
||||
import com.anytypeio.anytype.domain.objects.SetObjectIsArchived
|
||||
import com.anytypeio.anytype.domain.page.*
|
||||
|
@ -214,6 +215,9 @@ open class EditorViewModelTest {
|
|||
@Mock
|
||||
lateinit var objectTypesProvider: ObjectTypesProvider
|
||||
|
||||
@Mock
|
||||
lateinit var getDefaultEditorType: GetDefaultEditorType
|
||||
|
||||
private lateinit var updateDetail: UpdateDetail
|
||||
|
||||
lateinit var vm: EditorViewModel
|
||||
|
@ -2406,49 +2410,6 @@ open class EditorViewModelTest {
|
|||
coroutineTestRule.advanceTime(EditorViewModel.TEXT_CHANGES_DEBOUNCE_DURATION)
|
||||
}
|
||||
|
||||
@Test
|
||||
fun `should proceed with creating a new page with is draft true on on-plus-button-clicked event`() {
|
||||
|
||||
val root = MockDataFactory.randomUuid()
|
||||
val child = MockDataFactory.randomUuid()
|
||||
|
||||
val page = MockBlockFactory.makeOnePageWithOneTextBlock(
|
||||
root = root,
|
||||
child = child
|
||||
)
|
||||
|
||||
val flow: Flow<List<Event.Command>> = flow {
|
||||
delay(100)
|
||||
emit(
|
||||
listOf(
|
||||
Event.Command.ShowObject(
|
||||
root = root,
|
||||
blocks = page,
|
||||
context = root
|
||||
)
|
||||
)
|
||||
)
|
||||
}
|
||||
|
||||
stubObserveEvents(flow)
|
||||
stubOpenPage()
|
||||
buildViewModel()
|
||||
|
||||
vm.onStart(root)
|
||||
|
||||
coroutineTestRule.advanceTime(100)
|
||||
|
||||
// TESTING
|
||||
|
||||
vm.onPlusButtonPressed()
|
||||
|
||||
verify(createPage, times(1)).invoke(
|
||||
scope = any(),
|
||||
params = eq(CreatePage.Params(null, true)),
|
||||
onResult = any()
|
||||
)
|
||||
}
|
||||
|
||||
@Test
|
||||
fun `should start downloading file`() {
|
||||
|
||||
|
@ -3885,6 +3846,12 @@ open class EditorViewModelTest {
|
|||
}
|
||||
}
|
||||
|
||||
private fun stubGetDefaultObjectType(type: String?) {
|
||||
getDefaultEditorType.stub {
|
||||
onBlocking { invoke(Unit) } doReturn Either.Right(GetDefaultEditorType.Response(type))
|
||||
}
|
||||
}
|
||||
|
||||
fun buildViewModel(urlBuilder: UrlBuilder = builder) {
|
||||
|
||||
val storage = Editor.Storage()
|
||||
|
@ -3915,6 +3882,7 @@ open class EditorViewModelTest {
|
|||
createDocument = createDocument,
|
||||
createNewDocument = createNewDocument,
|
||||
analytics = analytics,
|
||||
getDefaultEditorType = getDefaultEditorType,
|
||||
orchestrator = Orchestrator(
|
||||
createBlock = createBlock,
|
||||
replaceBlock = replaceBlock,
|
||||
|
|
|
@ -0,0 +1,151 @@
|
|||
package com.anytypeio.anytype.presentation.editor.editor
|
||||
|
||||
import MockDataFactory
|
||||
import android.util.Log
|
||||
import androidx.arch.core.executor.testing.InstantTaskExecutorRule
|
||||
import com.anytypeio.anytype.core_models.*
|
||||
import com.anytypeio.anytype.presentation.MockTypicalDocumentFactory
|
||||
import com.anytypeio.anytype.presentation.editor.EditorViewModel
|
||||
import com.anytypeio.anytype.presentation.editor.editor.model.BlockView
|
||||
import com.anytypeio.anytype.presentation.relations.DocumentRelationView
|
||||
import com.anytypeio.anytype.presentation.util.CoroutinesTestRule
|
||||
import com.jraska.livedata.test
|
||||
import net.lachlanmckee.timberjunit.TimberTestRule
|
||||
import org.junit.After
|
||||
import org.junit.Before
|
||||
import org.junit.Rule
|
||||
import org.junit.Test
|
||||
import org.mockito.MockitoAnnotations
|
||||
|
||||
class EditorNoteLayoutTest : EditorPresentationTestSetup() {
|
||||
|
||||
@get:Rule
|
||||
val timberTestRule: TimberTestRule = TimberTestRule.builder()
|
||||
.minPriority(Log.DEBUG)
|
||||
.showThread(true)
|
||||
.showTimestamp(false)
|
||||
.onlyLogWhenTestFails(true)
|
||||
.build()
|
||||
|
||||
@get:Rule
|
||||
val rule = InstantTaskExecutorRule()
|
||||
|
||||
@get:Rule
|
||||
val coroutineTestRule = CoroutinesTestRule()
|
||||
|
||||
@Before
|
||||
fun setup() {
|
||||
MockitoAnnotations.openMocks(this)
|
||||
}
|
||||
|
||||
@After
|
||||
fun after() {
|
||||
coroutineTestRule.advanceTime(EditorViewModel.TEXT_CHANGES_DEBOUNCE_DURATION)
|
||||
}
|
||||
|
||||
@Test
|
||||
fun `should render note title block with featured relations block`() {
|
||||
|
||||
val featuredBlock = Block(
|
||||
id = "featuredRelations",
|
||||
fields = Block.Fields.empty(),
|
||||
children = emptyList(),
|
||||
content = Block.Content.FeaturedRelations
|
||||
)
|
||||
|
||||
val header = Block(
|
||||
id = "header",
|
||||
content = Block.Content.Layout(
|
||||
type = Block.Content.Layout.Type.HEADER
|
||||
),
|
||||
fields = Block.Fields.empty(),
|
||||
children = listOf(featuredBlock.id)
|
||||
)
|
||||
|
||||
val page = Block(
|
||||
id = root,
|
||||
fields = Block.Fields(emptyMap()),
|
||||
content = Block.Content.Smart(SmartBlockType.PAGE),
|
||||
children = listOf(header.id)
|
||||
)
|
||||
|
||||
val doc = listOf(page, header, featuredBlock)
|
||||
|
||||
val objectTypeId = "objectTypeId"
|
||||
val objectTypeName = "objectTypeName"
|
||||
val objectTypeDescription = "objectTypeDesc"
|
||||
|
||||
val r1 = MockTypicalDocumentFactory.relation("Ad")
|
||||
val r2 = MockTypicalDocumentFactory.relation("De")
|
||||
val r3 = MockTypicalDocumentFactory.relation("HJ")
|
||||
val relationObjectType = Relation(
|
||||
key = Block.Fields.TYPE_KEY,
|
||||
name = "Object Type",
|
||||
format = Relation.Format.OBJECT,
|
||||
source = Relation.Source.DERIVED
|
||||
)
|
||||
|
||||
|
||||
val value1 = MockDataFactory.randomString()
|
||||
val value2 = MockDataFactory.randomString()
|
||||
val value3 = MockDataFactory.randomString()
|
||||
val objectFields = Block.Fields(
|
||||
mapOf(
|
||||
r1.key to value1,
|
||||
r2.key to value2,
|
||||
r3.key to value3,
|
||||
relationObjectType.key to objectTypeId,
|
||||
Relations.FEATURED_RELATIONS to listOf(relationObjectType.key),
|
||||
Relations.LAYOUT to ObjectType.Layout.NOTE.code.toDouble()
|
||||
)
|
||||
)
|
||||
|
||||
val objectTypeFields = Block.Fields(
|
||||
mapOf(
|
||||
Block.Fields.NAME_KEY to objectTypeName,
|
||||
Block.Fields.DESCRIPTION_KEY to objectTypeDescription
|
||||
)
|
||||
)
|
||||
val customDetails = Block.Details(
|
||||
mapOf(
|
||||
root to objectFields,
|
||||
objectTypeId to objectTypeFields
|
||||
)
|
||||
)
|
||||
|
||||
stubInterceptEvents()
|
||||
stubInterceptThreadStatus()
|
||||
stubGetObjectTypes(objectTypes = listOf())
|
||||
stubGetDefaultObjectType(null)
|
||||
stubOpenDocument(
|
||||
document = doc,
|
||||
details = customDetails,
|
||||
relations = listOf(r1, r2, r3, relationObjectType)
|
||||
)
|
||||
|
||||
val vm = buildViewModel()
|
||||
|
||||
vm.onStart(root)
|
||||
|
||||
val expected = listOf(
|
||||
BlockView.TitleNote(
|
||||
id = BlockView.TitleNote.INTERNAL_ID
|
||||
),
|
||||
BlockView.FeaturedRelation(
|
||||
id = featuredBlock.id,
|
||||
relations = listOf(
|
||||
DocumentRelationView.ObjectType(
|
||||
relationId = relationObjectType.key,
|
||||
name = objectTypeName,
|
||||
value = null,
|
||||
isFeatured = true,
|
||||
type = objectTypeId
|
||||
)
|
||||
)
|
||||
)
|
||||
)
|
||||
|
||||
vm.state.test().assertValue(ViewState.Success(expected))
|
||||
}
|
||||
|
||||
}
|
|
@ -0,0 +1,253 @@
|
|||
package com.anytypeio.anytype.presentation.editor.editor
|
||||
|
||||
import MockDataFactory
|
||||
import android.util.Log
|
||||
import androidx.arch.core.executor.testing.InstantTaskExecutorRule
|
||||
import com.anytypeio.anytype.core_models.Block
|
||||
import com.anytypeio.anytype.core_models.ObjectType
|
||||
import com.anytypeio.anytype.core_models.SmartBlockType
|
||||
import com.anytypeio.anytype.presentation.editor.EditorViewModel
|
||||
import com.anytypeio.anytype.presentation.util.CoroutinesTestRule
|
||||
import net.lachlanmckee.timberjunit.TimberTestRule
|
||||
import org.junit.After
|
||||
import org.junit.Before
|
||||
import org.junit.Rule
|
||||
import org.junit.Test
|
||||
import org.mockito.MockitoAnnotations
|
||||
import kotlin.test.assertFalse
|
||||
import kotlin.test.assertNotNull
|
||||
import kotlin.test.assertTrue
|
||||
|
||||
class EditorObjectTypeChangeWidgetTest : EditorPresentationTestSetup() {
|
||||
|
||||
@get:Rule
|
||||
val timberTestRule: TimberTestRule = TimberTestRule.builder()
|
||||
.minPriority(Log.DEBUG)
|
||||
.showThread(true)
|
||||
.showTimestamp(false)
|
||||
.onlyLogWhenTestFails(true)
|
||||
.build()
|
||||
|
||||
@get:Rule
|
||||
val rule = InstantTaskExecutorRule()
|
||||
|
||||
@get:Rule
|
||||
val coroutineTestRule = CoroutinesTestRule()
|
||||
|
||||
@Before
|
||||
fun setup() {
|
||||
MockitoAnnotations.openMocks(this)
|
||||
}
|
||||
|
||||
@After
|
||||
fun after() {
|
||||
coroutineTestRule.advanceTime(EditorViewModel.TEXT_CHANGES_DEBOUNCE_DURATION)
|
||||
}
|
||||
|
||||
@Test
|
||||
fun `should show widget on note object with one empty text block`() {
|
||||
|
||||
val paragraph = Block(
|
||||
id = MockDataFactory.randomUuid(),
|
||||
fields = Block.Fields.empty(),
|
||||
children = emptyList(),
|
||||
content = Block.Content.Text(
|
||||
text = "",
|
||||
marks = emptyList(),
|
||||
style = Block.Content.Text.Style.P
|
||||
)
|
||||
)
|
||||
|
||||
val featuredBlock = Block(
|
||||
id = "featuredRelations",
|
||||
fields = Block.Fields.empty(),
|
||||
children = emptyList(),
|
||||
content = Block.Content.FeaturedRelations
|
||||
)
|
||||
|
||||
val header = Block(
|
||||
id = "header",
|
||||
content = Block.Content.Layout(
|
||||
type = Block.Content.Layout.Type.HEADER
|
||||
),
|
||||
fields = Block.Fields.empty(),
|
||||
children = listOf(featuredBlock.id)
|
||||
)
|
||||
|
||||
val page = Block(
|
||||
id = root,
|
||||
fields = Block.Fields(emptyMap()),
|
||||
content = Block.Content.Smart(SmartBlockType.PAGE),
|
||||
children = listOf(header.id, paragraph.id)
|
||||
)
|
||||
|
||||
val doc = listOf(page, header, paragraph, featuredBlock)
|
||||
|
||||
val objectDetails = Block.Fields(
|
||||
mapOf(
|
||||
"type" to ObjectType.NOTE_URL,
|
||||
"layout" to ObjectType.Layout.NOTE.code.toDouble()
|
||||
)
|
||||
)
|
||||
|
||||
val detailsList = Block.Details(details = mapOf(root to objectDetails))
|
||||
|
||||
stubInterceptEvents()
|
||||
stubInterceptThreadStatus()
|
||||
stubGetObjectTypes(objectTypes = listOf())
|
||||
stubGetDefaultObjectType(type = ObjectType.NOTE_URL)
|
||||
stubOpenDocument(
|
||||
document = doc,
|
||||
details = detailsList
|
||||
)
|
||||
|
||||
val vm = buildViewModel()
|
||||
|
||||
vm.onStart(root)
|
||||
|
||||
val state = vm.controlPanelViewState.value
|
||||
|
||||
val objectTypesWidget = state?.objectTypesToolbar
|
||||
|
||||
assertNotNull(objectTypesWidget)
|
||||
assertTrue(objectTypesWidget.isVisible)
|
||||
}
|
||||
|
||||
@Test
|
||||
fun `should not show widget on note object with one not empty text block`() {
|
||||
|
||||
val paragraph = Block(
|
||||
id = MockDataFactory.randomUuid(),
|
||||
fields = Block.Fields.empty(),
|
||||
children = emptyList(),
|
||||
content = Block.Content.Text(
|
||||
text = "F",
|
||||
marks = emptyList(),
|
||||
style = Block.Content.Text.Style.P
|
||||
)
|
||||
)
|
||||
|
||||
val featuredBlock = Block(
|
||||
id = "featuredRelations",
|
||||
fields = Block.Fields.empty(),
|
||||
children = emptyList(),
|
||||
content = Block.Content.FeaturedRelations
|
||||
)
|
||||
|
||||
val header = Block(
|
||||
id = "header",
|
||||
content = Block.Content.Layout(
|
||||
type = Block.Content.Layout.Type.HEADER
|
||||
),
|
||||
fields = Block.Fields.empty(),
|
||||
children = listOf(featuredBlock.id)
|
||||
)
|
||||
|
||||
val page = Block(
|
||||
id = root,
|
||||
fields = Block.Fields(emptyMap()),
|
||||
content = Block.Content.Smart(SmartBlockType.PAGE),
|
||||
children = listOf(header.id, paragraph.id)
|
||||
)
|
||||
|
||||
val doc = listOf(page, header, paragraph, featuredBlock)
|
||||
|
||||
val objectDetails = Block.Fields(
|
||||
mapOf(
|
||||
"type" to ObjectType.NOTE_URL,
|
||||
"layout" to ObjectType.Layout.NOTE.code.toDouble()
|
||||
)
|
||||
)
|
||||
|
||||
val detailsList = Block.Details(details = mapOf(root to objectDetails))
|
||||
|
||||
stubInterceptEvents()
|
||||
stubInterceptThreadStatus()
|
||||
stubGetObjectTypes(objectTypes = listOf())
|
||||
stubGetDefaultObjectType(type = ObjectType.NOTE_URL)
|
||||
stubOpenDocument(
|
||||
document = doc,
|
||||
details = detailsList
|
||||
)
|
||||
|
||||
val vm = buildViewModel()
|
||||
|
||||
vm.onStart(root)
|
||||
|
||||
val state = vm.controlPanelViewState.value
|
||||
|
||||
val objectTypesWidget = state?.objectTypesToolbar
|
||||
|
||||
assertNotNull(objectTypesWidget)
|
||||
assertFalse(objectTypesWidget.isVisible)
|
||||
}
|
||||
|
||||
@Test
|
||||
fun `should show widget on note object layout with one empty text block and default not note type`() {
|
||||
|
||||
val paragraph = Block(
|
||||
id = MockDataFactory.randomUuid(),
|
||||
fields = Block.Fields.empty(),
|
||||
children = emptyList(),
|
||||
content = Block.Content.Text(
|
||||
text = "",
|
||||
marks = emptyList(),
|
||||
style = Block.Content.Text.Style.P
|
||||
)
|
||||
)
|
||||
|
||||
val featuredBlock = Block(
|
||||
id = "featuredRelations",
|
||||
fields = Block.Fields.empty(),
|
||||
children = emptyList(),
|
||||
content = Block.Content.FeaturedRelations
|
||||
)
|
||||
|
||||
val header = Block(
|
||||
id = "header",
|
||||
content = Block.Content.Layout(
|
||||
type = Block.Content.Layout.Type.HEADER
|
||||
),
|
||||
fields = Block.Fields.empty(),
|
||||
children = listOf(featuredBlock.id)
|
||||
)
|
||||
|
||||
val page = Block(
|
||||
id = root,
|
||||
fields = Block.Fields(emptyMap()),
|
||||
content = Block.Content.Smart(SmartBlockType.PAGE),
|
||||
children = listOf(header.id, paragraph.id)
|
||||
)
|
||||
|
||||
val doc = listOf(page, header, paragraph, featuredBlock)
|
||||
|
||||
val objectDetails = Block.Fields(
|
||||
mapOf(
|
||||
"type" to ObjectType.NOTE_URL,
|
||||
"layout" to ObjectType.Layout.NOTE.code.toDouble()
|
||||
)
|
||||
)
|
||||
|
||||
val detailsList = Block.Details(details = mapOf(root to objectDetails))
|
||||
|
||||
stubInterceptEvents()
|
||||
stubInterceptThreadStatus()
|
||||
stubGetObjectTypes(objectTypes = listOf())
|
||||
stubGetDefaultObjectType(type = ObjectType.PAGE_URL)
|
||||
stubOpenDocument(
|
||||
document = doc,
|
||||
details = detailsList
|
||||
)
|
||||
|
||||
val vm = buildViewModel()
|
||||
|
||||
vm.onStart(root)
|
||||
|
||||
val state = vm.controlPanelViewState.value
|
||||
|
||||
val objectTypesWidget = state?.objectTypesToolbar
|
||||
|
||||
assertNotNull(objectTypesWidget)
|
||||
assertTrue(objectTypesWidget.isVisible)
|
||||
}
|
||||
}
|
|
@ -20,6 +20,7 @@ import com.anytypeio.anytype.domain.dataview.interactor.SearchObjects
|
|||
import com.anytypeio.anytype.domain.dataview.interactor.SetRelationKey
|
||||
import com.anytypeio.anytype.domain.download.DownloadFile
|
||||
import com.anytypeio.anytype.domain.event.interactor.InterceptEvents
|
||||
import com.anytypeio.anytype.domain.launch.GetDefaultEditorType
|
||||
import com.anytypeio.anytype.domain.misc.UrlBuilder
|
||||
import com.anytypeio.anytype.domain.objects.SetObjectIsArchived
|
||||
import com.anytypeio.anytype.domain.page.*
|
||||
|
@ -184,6 +185,9 @@ open class EditorPresentationTestSetup {
|
|||
@Mock
|
||||
lateinit var searchObjects: SearchObjects
|
||||
|
||||
@Mock
|
||||
lateinit var getDefaultEditorType: GetDefaultEditorType
|
||||
|
||||
private val builder: UrlBuilder get() = UrlBuilder(gateway)
|
||||
|
||||
private lateinit var updateDetail: UpdateDetail
|
||||
|
@ -266,7 +270,8 @@ open class EditorPresentationTestSetup {
|
|||
updateDetail = updateDetail,
|
||||
getCompatibleObjectTypes = getCompatibleObjectTypes,
|
||||
objectTypesProvider = objectTypesProvider,
|
||||
searchObjects = searchObjects
|
||||
searchObjects = searchObjects,
|
||||
getDefaultEditorType = getDefaultEditorType
|
||||
)
|
||||
}
|
||||
|
||||
|
@ -514,4 +519,10 @@ open class EditorPresentationTestSetup {
|
|||
onBlocking { invoke(any()) } doReturn Either.Right(listOf())
|
||||
}
|
||||
}
|
||||
|
||||
fun stubGetDefaultObjectType(type: String?) {
|
||||
getDefaultEditorType.stub {
|
||||
onBlocking { invoke(Unit) } doReturn Either.Right(GetDefaultEditorType.Response(type))
|
||||
}
|
||||
}
|
||||
}
|
|
@ -1,6 +1,5 @@
|
|||
package com.anytypeio.anytype.presentation.splash
|
||||
|
||||
import MockDataFactory
|
||||
import androidx.arch.core.executor.testing.InstantTaskExecutorRule
|
||||
import com.anytypeio.anytype.analytics.base.Analytics
|
||||
import com.anytypeio.anytype.core_models.ObjectType
|
||||
|
@ -15,8 +14,8 @@ import com.anytypeio.anytype.domain.base.Either
|
|||
import com.anytypeio.anytype.domain.block.interactor.sets.StoreObjectTypes
|
||||
import com.anytypeio.anytype.domain.block.repo.BlockRepository
|
||||
import com.anytypeio.anytype.domain.config.UserSettingsRepository
|
||||
import com.anytypeio.anytype.domain.launch.GetDefaultPageType
|
||||
import com.anytypeio.anytype.domain.launch.SetDefaultPageType
|
||||
import com.anytypeio.anytype.domain.launch.GetDefaultEditorType
|
||||
import com.anytypeio.anytype.domain.launch.SetDefaultEditorType
|
||||
import com.anytypeio.anytype.presentation.util.CoroutinesTestRule
|
||||
import kotlinx.coroutines.runBlocking
|
||||
import org.junit.Before
|
||||
|
@ -62,10 +61,10 @@ class SplashViewModelTest {
|
|||
private lateinit var getLastOpenedObject: GetLastOpenedObject
|
||||
|
||||
@Mock
|
||||
private lateinit var setDefaultPageType: SetDefaultPageType
|
||||
private lateinit var setDefaultEditorType: SetDefaultEditorType
|
||||
|
||||
@Mock
|
||||
private lateinit var getDefaultPageType: GetDefaultPageType
|
||||
private lateinit var getDefaultEditorType: GetDefaultEditorType
|
||||
|
||||
lateinit var vm: SplashViewModel
|
||||
|
||||
|
@ -90,8 +89,8 @@ class SplashViewModelTest {
|
|||
analytics = analytics,
|
||||
storeObjectTypes = storeObjectTypes,
|
||||
getLastOpenedObject = getLastOpenedObject,
|
||||
setDefaultPageType = setDefaultPageType,
|
||||
getDefaultPageType = getDefaultPageType
|
||||
setDefaultEditorType = setDefaultEditorType,
|
||||
getDefaultEditorType = getDefaultEditorType
|
||||
)
|
||||
}
|
||||
|
||||
|
@ -125,14 +124,14 @@ class SplashViewModelTest {
|
|||
stubLaunchWallet()
|
||||
stubLaunchAccount()
|
||||
stubGetLastOpenedObject()
|
||||
getDefaultPageType.stub {
|
||||
getDefaultEditorType.stub {
|
||||
onBlocking { invoke(Unit) } doReturn Either.Left(Exception("error"))
|
||||
}
|
||||
|
||||
initViewModel()
|
||||
|
||||
runBlocking {
|
||||
verify(getDefaultPageType, times(1)).invoke(any())
|
||||
verify(getDefaultEditorType, times(1)).invoke(any())
|
||||
verify(checkAuthorizationStatus, times(1)).invoke(any())
|
||||
}
|
||||
}
|
||||
|
@ -151,7 +150,7 @@ class SplashViewModelTest {
|
|||
initViewModel()
|
||||
|
||||
runBlocking {
|
||||
verify(getDefaultPageType, times(1)).invoke(any())
|
||||
verify(getDefaultEditorType, times(1)).invoke(any())
|
||||
verify(checkAuthorizationStatus, times(1)).invoke(any())
|
||||
}
|
||||
}
|
||||
|
@ -312,14 +311,14 @@ class SplashViewModelTest {
|
|||
}
|
||||
|
||||
private fun stubGetDefaultObjectType(type: String?) {
|
||||
getDefaultPageType.stub {
|
||||
onBlocking { invoke(Unit) } doReturn Either.Right(GetDefaultPageType.Response(type))
|
||||
getDefaultEditorType.stub {
|
||||
onBlocking { invoke(Unit) } doReturn Either.Right(GetDefaultEditorType.Response(type))
|
||||
}
|
||||
}
|
||||
|
||||
private fun stubSetDefaultObjectType(type: String) {
|
||||
setDefaultPageType.stub {
|
||||
onBlocking { invoke(SetDefaultPageType.Params(type)) } doReturn Either.Right(Unit)
|
||||
setDefaultEditorType.stub {
|
||||
onBlocking { invoke(SetDefaultEditorType.Params(type)) } doReturn Either.Right(Unit)
|
||||
}
|
||||
}
|
||||
}
|
Loading…
Add table
Add a link
Reference in a new issue