Compare commits
22 Commits
main
...
release/0-
Author | SHA1 | Date | |
---|---|---|---|
|
06d6e81b65 | ||
|
3684f79d29 | ||
|
58a0b10183 | ||
|
7c6b4684d5 | ||
|
ed9f41ac02 | ||
|
705367d56f | ||
|
3ae86e0c65 | ||
|
9d12987a9f | ||
|
9e951951db | ||
|
8a5454869f | ||
|
f91807f89a | ||
|
454e586222 | ||
|
32c740f246 | ||
|
cfcac55a48 | ||
|
91591e116c | ||
|
9bdf830a70 | ||
|
6a5ab68eda | ||
|
33e6488d54 | ||
|
c50be0a8e5 | ||
|
b47dd59a21 | ||
|
6563e138a6 | ||
|
3949a47a66 |
|
@ -148,6 +148,14 @@ object EventsDictionary {
|
|||
const val screenHome = "ScreenHome"
|
||||
const val selectHomeTab = "SelectHomeTab"
|
||||
|
||||
//Templates
|
||||
const val selectTemplate = "SelectTemplate"
|
||||
const val clickNewOption = "ClickNewOption"
|
||||
const val changeDefaultTemplate = "ChangeDefaultTemplate"
|
||||
const val editTemplate = "EditTemplate"
|
||||
const val duplicateTemplate = "DuplicateTemplate"
|
||||
const val createTemplate = "CreateTemplate"
|
||||
|
||||
// Onboarding events
|
||||
const val screenOnboarding = "ScreenOnboarding"
|
||||
const val clickOnboarding = "ClickOnboarding"
|
||||
|
|
|
@ -36,6 +36,9 @@ class AmplitudeTracker(
|
|||
analytics
|
||||
.observeEvents()
|
||||
.collect { event ->
|
||||
if (BuildConfig.DEBUG) {
|
||||
Timber.d("Analytics Amplitude(event = $event)")
|
||||
}
|
||||
if (BuildConfig.SEND_EVENTS && event is EventAnalytics.Anytype) {
|
||||
val props = event.props.getEventProperties(
|
||||
startTime = event.duration?.start,
|
||||
|
@ -43,9 +46,6 @@ class AmplitudeTracker(
|
|||
renderTime = event.duration?.render
|
||||
)
|
||||
tracker.logEvent(event.name, props)
|
||||
if (BuildConfig.DEBUG) {
|
||||
Timber.d("Analytics Amplitude(event = $event)")
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
version.versionMajor=0
|
||||
version.versionMinor=24
|
||||
version.versionPatch=0
|
||||
version.versionPatch=7
|
||||
version.useDatedVersionName=false
|
||||
|
|
|
@ -60,6 +60,7 @@ import com.anytypeio.anytype.domain.launch.GetDefaultPageType
|
|||
import com.anytypeio.anytype.domain.misc.UrlBuilder
|
||||
import com.anytypeio.anytype.domain.`object`.ConvertObjectToCollection
|
||||
import com.anytypeio.anytype.domain.`object`.ConvertObjectToSet
|
||||
import com.anytypeio.anytype.domain.`object`.SetObjectInternalFlags
|
||||
import com.anytypeio.anytype.domain.`object`.UpdateDetail
|
||||
import com.anytypeio.anytype.domain.objects.DefaultStoreOfObjectTypes
|
||||
import com.anytypeio.anytype.domain.objects.DefaultStoreOfRelations
|
||||
|
@ -269,6 +270,9 @@ open class EditorTestSetup {
|
|||
@Mock
|
||||
lateinit var fileLimitsEventChannel: FileLimitsEventChannel
|
||||
|
||||
@Mock
|
||||
lateinit var setObjectInternalFlags: SetObjectInternalFlags
|
||||
|
||||
lateinit var interceptFileLimitEvents: InterceptFileLimitEvents
|
||||
|
||||
lateinit var addRelationToObject: AddRelationToObject
|
||||
|
@ -466,7 +470,8 @@ open class EditorTestSetup {
|
|||
getObjectTypes = getObjectTypes,
|
||||
objectToCollection = objectToCollection,
|
||||
interceptFileLimitEvents = interceptFileLimitEvents,
|
||||
addRelationToObject = addRelationToObject
|
||||
addRelationToObject = addRelationToObject,
|
||||
setObjectInternalFlags = setObjectInternalFlags
|
||||
)
|
||||
}
|
||||
|
||||
|
|
|
@ -56,6 +56,7 @@ import com.anytypeio.anytype.domain.misc.UrlBuilder
|
|||
import com.anytypeio.anytype.domain.`object`.ConvertObjectToCollection
|
||||
import com.anytypeio.anytype.domain.`object`.ConvertObjectToSet
|
||||
import com.anytypeio.anytype.domain.`object`.DuplicateObject
|
||||
import com.anytypeio.anytype.domain.`object`.SetObjectInternalFlags
|
||||
import com.anytypeio.anytype.domain.`object`.UpdateDetail
|
||||
import com.anytypeio.anytype.domain.objects.SetObjectIsArchived
|
||||
import com.anytypeio.anytype.domain.objects.StoreOfObjectTypes
|
||||
|
@ -233,6 +234,14 @@ object EditorSessionModule {
|
|||
dispatchers: AppCoroutineDispatchers
|
||||
) : InterceptFileLimitEvents = InterceptFileLimitEvents(channel, dispatchers)
|
||||
|
||||
@JvmStatic
|
||||
@Provides
|
||||
@PerScreen
|
||||
fun provideSetObjectInternalFlags(
|
||||
repo: BlockRepository,
|
||||
dispatchers: AppCoroutineDispatchers
|
||||
) : SetObjectInternalFlags = SetObjectInternalFlags(repo, dispatchers)
|
||||
|
||||
@JvmStatic
|
||||
@Provides
|
||||
fun providePageViewModelFactory(
|
||||
|
@ -271,7 +280,8 @@ object EditorSessionModule {
|
|||
getObjectTypes: GetObjectTypes,
|
||||
objectToCollection: ConvertObjectToCollection,
|
||||
interceptFileLimitEvents: InterceptFileLimitEvents,
|
||||
addRelationToObject: AddRelationToObject
|
||||
addRelationToObject: AddRelationToObject,
|
||||
setObjectInternalFlags: SetObjectInternalFlags
|
||||
): EditorViewModelFactory = EditorViewModelFactory(
|
||||
openPage = openPage,
|
||||
closeObject = closePage,
|
||||
|
@ -308,7 +318,8 @@ object EditorSessionModule {
|
|||
getObjectTypes = getObjectTypes,
|
||||
objectToCollection = objectToCollection,
|
||||
interceptFileLimitEvents = interceptFileLimitEvents,
|
||||
addRelationToObject = addRelationToObject
|
||||
addRelationToObject = addRelationToObject,
|
||||
setObjectInternalFlags = setObjectInternalFlags
|
||||
)
|
||||
|
||||
|
||||
|
|
|
@ -59,6 +59,7 @@ import dagger.Module
|
|||
import dagger.Provides
|
||||
import javax.inject.Named
|
||||
import javax.inject.Singleton
|
||||
import timber.log.Timber
|
||||
|
||||
@Module(includes = [DataModule.Bindings::class])
|
||||
object DataModule {
|
||||
|
@ -162,8 +163,22 @@ object DataModule {
|
|||
@Named("encrypted")
|
||||
fun provideEncryptedSharedPreferences(
|
||||
context: Context
|
||||
): SharedPreferences = EncryptedSharedPreferences.create(
|
||||
"encrypted_prefs",
|
||||
): SharedPreferences = try {
|
||||
initializeEncryptedPrefs(context)
|
||||
} catch (e: Exception) {
|
||||
// https://issuetracker.google.com/issues/164901843
|
||||
Timber.e(e, "Error while initializing encrypted prefs")
|
||||
// Clearing pre-existing prefs
|
||||
context
|
||||
.getSharedPreferences(ENCRYPTED_PREFS_NAME, Context.MODE_PRIVATE)
|
||||
.edit()
|
||||
.clear()
|
||||
.commit()
|
||||
initializeEncryptedPrefs(context)
|
||||
}
|
||||
|
||||
private fun initializeEncryptedPrefs(context: Context) = EncryptedSharedPreferences.create(
|
||||
ENCRYPTED_PREFS_NAME,
|
||||
MasterKeys.getOrCreate(MasterKeys.AES256_GCM_SPEC),
|
||||
context,
|
||||
EncryptedSharedPreferences.PrefKeyEncryptionScheme.AES256_SIV,
|
||||
|
@ -311,4 +326,6 @@ object DataModule {
|
|||
@Singleton
|
||||
fun bindMiddlewareService(middleware: MiddlewareServiceImplementation): MiddlewareService
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
const val ENCRYPTED_PREFS_NAME = "encrypted_prefs"
|
|
@ -538,7 +538,6 @@ class OnboardingFragment : Fragment() {
|
|||
navController.navigate(
|
||||
route = OnboardingNavigation.createSoulAnim
|
||||
)
|
||||
vm.sendAnalyticsOnboardingScreen()
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -5,9 +5,7 @@ import android.view.LayoutInflater
|
|||
import android.view.View
|
||||
import android.view.ViewGroup
|
||||
import androidx.fragment.app.viewModels
|
||||
import androidx.lifecycle.Lifecycle
|
||||
import androidx.lifecycle.lifecycleScope
|
||||
import androidx.lifecycle.repeatOnLifecycle
|
||||
import androidx.navigation.fragment.findNavController
|
||||
import com.anytypeio.anytype.R
|
||||
import com.anytypeio.anytype.core_models.Id
|
||||
|
@ -20,7 +18,6 @@ import com.anytypeio.anytype.databinding.FragmentTemplateSelectBinding
|
|||
import com.anytypeio.anytype.di.common.componentManager
|
||||
import com.anytypeio.anytype.presentation.templates.TemplateSelectViewModel
|
||||
import com.google.android.material.tabs.TabLayoutMediator
|
||||
import kotlinx.coroutines.launch
|
||||
import javax.inject.Inject
|
||||
|
||||
class TemplateSelectFragment :
|
||||
|
@ -40,9 +37,15 @@ class TemplateSelectFragment :
|
|||
override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
|
||||
super.onViewCreated(view, savedInstanceState)
|
||||
setupViewPagerAndTabs()
|
||||
viewLifecycleOwner.lifecycleScope.launch {
|
||||
viewLifecycleOwner.repeatOnLifecycle(Lifecycle.State.STARTED) {
|
||||
setupClickEventHandlers()
|
||||
with(lifecycleScope) {
|
||||
subscribe(binding.btnSkip.clicks()) {
|
||||
vm.onSkipButtonClicked()
|
||||
}
|
||||
subscribe(binding.btnUseTemplate.clicks()) {
|
||||
vm.onUseTemplateButtonPressed(
|
||||
currentItem = binding.templateViewPager.currentItem,
|
||||
ctx = ctx
|
||||
)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -53,11 +56,6 @@ class TemplateSelectFragment :
|
|||
TabLayoutMediator(binding.tabs, binding.templateViewPager) { _, _ -> }.attach()
|
||||
}
|
||||
|
||||
private suspend fun setupClickEventHandlers() {
|
||||
setupUseTemplateClicks()
|
||||
setupCancelClicks()
|
||||
}
|
||||
|
||||
override fun onStart() {
|
||||
jobs += lifecycleScope.subscribe(vm.viewState) { render(it) }
|
||||
jobs += lifecycleScope.subscribe(vm.isDismissed) { if (it) exit() }
|
||||
|
@ -67,10 +65,9 @@ class TemplateSelectFragment :
|
|||
|
||||
private fun render(viewState: TemplateSelectViewModel.ViewState) {
|
||||
when (viewState) {
|
||||
TemplateSelectViewModel.ViewState.ErrorGettingType -> TODO()
|
||||
TemplateSelectViewModel.ViewState.Init -> {
|
||||
binding.tvTemplateCountOrTutorial.text = null
|
||||
binding.btnCancel.isEnabled = true
|
||||
binding.btnSkip.isEnabled = true
|
||||
binding.btnUseTemplate.isEnabled = false
|
||||
}
|
||||
|
||||
|
@ -86,19 +83,6 @@ class TemplateSelectFragment :
|
|||
}
|
||||
}
|
||||
|
||||
private suspend fun setupUseTemplateClicks() {
|
||||
binding.btnUseTemplate.clicks().collect {
|
||||
vm.onUseTemplateButtonPressed(
|
||||
currentItem = binding.templateViewPager.currentItem,
|
||||
ctx = ctx
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
private suspend fun setupCancelClicks() {
|
||||
binding.btnCancel.clicks().collect { exit() }
|
||||
}
|
||||
|
||||
private fun exit() {
|
||||
findNavController().popBackStack()
|
||||
}
|
||||
|
|
|
@ -40,9 +40,9 @@ fun TreeWidgetObjectIcon(
|
|||
is ObjectIcon.Profile.Avatar -> {
|
||||
Box(
|
||||
modifier = modifier
|
||||
.padding(start = paddingStart, end = paddingEnd)
|
||||
.height(18.dp)
|
||||
.width(18.dp)
|
||||
.padding(start = paddingStart, end = paddingEnd)
|
||||
.background(
|
||||
shape = CircleShape,
|
||||
color = colorResource(id = R.color.shape_primary)
|
||||
|
|
|
@ -5,7 +5,8 @@
|
|||
android:layout_width="match_parent"
|
||||
android:layout_height="match_parent"
|
||||
android:background="@color/defaultCanvasColor"
|
||||
android:orientation="vertical">
|
||||
android:orientation="vertical"
|
||||
tools:context="com.anytypeio.anytype.ui.templates.TemplateSelectFragment">
|
||||
|
||||
<com.google.android.material.tabs.TabLayout
|
||||
android:id="@+id/tabs"
|
||||
|
@ -44,14 +45,14 @@
|
|||
android:orientation="horizontal">
|
||||
|
||||
<com.anytypeio.anytype.core_ui.views.ButtonSecondaryLarge
|
||||
android:id="@+id/btnCancel"
|
||||
android:id="@+id/btnSkip"
|
||||
android:layout_width="0dp"
|
||||
android:layout_height="@dimen/dp_48"
|
||||
android:layout_gravity="center_vertical"
|
||||
android:layout_marginStart="20dp"
|
||||
android:layout_marginEnd="4dp"
|
||||
android:layout_weight="1"
|
||||
android:text="@string/cancel" />
|
||||
android:text="@string/skip" />
|
||||
|
||||
<com.anytypeio.anytype.core_ui.views.ButtonPrimaryLarge
|
||||
android:id="@+id/btnUseTemplate"
|
||||
|
|
|
@ -2,7 +2,7 @@ import com.android.build.gradle.LibraryPlugin
|
|||
|
||||
buildscript {
|
||||
ext.compile_sdk = 33
|
||||
ext.target_sdk = 32
|
||||
ext.target_sdk = 33
|
||||
ext.min_sdk = 26
|
||||
|
||||
ext.application_id = 'io.anytype.app'
|
||||
|
|
|
@ -421,4 +421,6 @@ sealed class Command {
|
|||
|
||||
data class AddObjectToCollection(val ctx: Id, val afterId: Id, val ids: List<Id>)
|
||||
data class SetQueryToSet(val ctx: Id, val query: String)
|
||||
|
||||
data class SetInternalFlags(val ctx: Id, val flags: List<InternalFlags>)
|
||||
}
|
|
@ -373,14 +373,20 @@ interface TextBlockHolder : TextHolder {
|
|||
private fun setupCustomInsertionActionMode(isWithBookmark: Boolean = true) {
|
||||
content.customInsertionActionModeCallback = object : ActionMode.Callback2() {
|
||||
override fun onCreateActionMode(mode: ActionMode, menu: Menu): Boolean {
|
||||
if (getLink() != null) {
|
||||
menu.addLink()
|
||||
if (isWithBookmark) {
|
||||
menu.add(0, R.id.menuBookmark, 3, R.string.bookmark)
|
||||
return try {
|
||||
if (getLink() != null) {
|
||||
menu.addLink()
|
||||
if (isWithBookmark) {
|
||||
menu.add(0, R.id.menuBookmark, 3, R.string.bookmark)
|
||||
}
|
||||
menu.pasteToText()
|
||||
}
|
||||
true
|
||||
} catch (e: Exception) {
|
||||
false.also {
|
||||
Timber.d(e, "Error while creating action mode")
|
||||
}
|
||||
menu.pasteToText()
|
||||
}
|
||||
return true
|
||||
}
|
||||
|
||||
override fun onPrepareActionMode(mode: ActionMode, menu: Menu): Boolean {
|
||||
|
@ -417,11 +423,17 @@ interface TextBlockHolder : TextHolder {
|
|||
}
|
||||
content.customSelectionActionModeCallback = object : ActionMode.Callback2() {
|
||||
override fun onCreateActionMode(mode: ActionMode, menu: Menu): Boolean {
|
||||
if (getLink() != null) {
|
||||
menu.addLink()
|
||||
menu.pasteToText()
|
||||
return try {
|
||||
if (getLink() != null) {
|
||||
menu.addLink()
|
||||
menu.pasteToText()
|
||||
}
|
||||
return true
|
||||
} catch (e: Exception) {
|
||||
false.also {
|
||||
Timber.d(e, "Error while creating action mode")
|
||||
}
|
||||
}
|
||||
return true
|
||||
}
|
||||
|
||||
override fun onPrepareActionMode(mode: ActionMode, menu: Menu): Boolean {
|
||||
|
|
|
@ -143,7 +143,7 @@ class BundledWidgetSourceHolder(
|
|||
BundledWidgetSourceView.Favorites -> {
|
||||
with(binding) {
|
||||
tvTitle.setText(R.string.favorites)
|
||||
tvSubtitle.setText(R.string.your_favorite_objects)
|
||||
tvSubtitle.text = ""
|
||||
ivIcon.setIcon(ObjectIcon.Basic.Emoji("⭐️"))
|
||||
}
|
||||
}
|
||||
|
@ -158,7 +158,7 @@ class BundledWidgetSourceHolder(
|
|||
BundledWidgetSourceView.RecentLocal -> {
|
||||
with(binding) {
|
||||
tvTitle.setText(R.string.recently_opened)
|
||||
tvSubtitle.setText(R.string.recently_opened_objects)
|
||||
tvSubtitle.setText(R.string.on_this_device)
|
||||
ivIcon.setIcon(ObjectIcon.Basic.Emoji("📅"))
|
||||
}
|
||||
}
|
||||
|
@ -166,14 +166,14 @@ class BundledWidgetSourceHolder(
|
|||
BundledWidgetSourceView.Sets -> {
|
||||
with(binding) {
|
||||
tvTitle.setText(R.string.sets)
|
||||
tvSubtitle.setText(R.string.sets_of_objects)
|
||||
tvSubtitle.text = ""
|
||||
ivIcon.setIcon(ObjectIcon.Basic.Emoji("📚"))
|
||||
}
|
||||
}
|
||||
BundledWidgetSourceView.Collections -> {
|
||||
with(binding) {
|
||||
tvTitle.setText(R.string.collections)
|
||||
tvSubtitle.setText(R.string.collection_widget_description)
|
||||
tvSubtitle.text = ""
|
||||
ivIcon.setIcon(ObjectIcon.Basic.Emoji("📂"))
|
||||
}
|
||||
}
|
||||
|
|
|
@ -5,6 +5,7 @@ import android.R.id.paste
|
|||
import android.content.Context
|
||||
import android.graphics.Canvas
|
||||
import android.os.Parcelable
|
||||
import android.text.InputType
|
||||
import android.text.Spanned
|
||||
import android.text.TextWatcher
|
||||
import android.text.util.Linkify
|
||||
|
@ -98,7 +99,12 @@ class TextInputWidget : AppCompatEditText {
|
|||
}
|
||||
|
||||
fun enableEditMode() {
|
||||
multilineIme(action = inputAction.toIMECode())
|
||||
setRawInputType(
|
||||
InputType.TYPE_CLASS_TEXT
|
||||
or InputType.TYPE_TEXT_FLAG_CAP_SENTENCES
|
||||
or InputType.TYPE_TEXT_FLAG_AUTO_CORRECT
|
||||
)
|
||||
imeOptions = inputAction.toIMECode()
|
||||
setTextIsSelectable(true)
|
||||
inReadMode = false
|
||||
}
|
||||
|
|
|
@ -113,6 +113,7 @@
|
|||
<string name="modal_table">Table</string>
|
||||
<string name="modal_list">List</string>
|
||||
<string name="cancel">Cancel</string>
|
||||
<string name="skip">Skip</string>
|
||||
<string name="add">Add</string>
|
||||
<string name="duplicate">Duplicate</string>
|
||||
<string name="customize_view">Customize view</string>
|
||||
|
@ -610,7 +611,7 @@
|
|||
<string name="object_search_recently_opened_section_title">Recently opened</string>
|
||||
<string name="widget_source_anytype_library">Anytype Library</string>
|
||||
<string name="your_favorite_objects">Your favorite objects</string>
|
||||
<string name="recently_opened_objects">Recently opened objects</string>
|
||||
<string name="on_this_device">On this device</string>
|
||||
<string name="sets_of_objects">Sets of objects from your workspace</string>
|
||||
|
||||
<string name="content_description_customize_view_button">Customize-view button</string>
|
||||
|
|
|
@ -841,4 +841,8 @@ class BlockDataRepository(
|
|||
override suspend fun fileSpaceUsage(): FileLimits {
|
||||
return remote.fileSpaceUsage()
|
||||
}
|
||||
|
||||
override suspend fun setInternalFlags(command: Command.SetInternalFlags): Payload {
|
||||
return remote.setInternalFlags(command)
|
||||
}
|
||||
}
|
|
@ -360,4 +360,6 @@ interface BlockRemote {
|
|||
suspend fun addObjectToCollection(command: Command.AddObjectToCollection): Payload
|
||||
suspend fun setQueryToSet(command: Command.SetQueryToSet): Payload
|
||||
suspend fun fileSpaceUsage(): FileLimits
|
||||
|
||||
suspend fun setInternalFlags(command: Command.SetInternalFlags): Payload
|
||||
}
|
|
@ -412,4 +412,5 @@ interface BlockRepository {
|
|||
suspend fun addObjectToCollection(command: Command.AddObjectToCollection): Payload
|
||||
suspend fun setQueryToSet(command: Command.SetQueryToSet): Payload
|
||||
suspend fun fileSpaceUsage(): FileLimits
|
||||
suspend fun setInternalFlags(command: Command.SetInternalFlags): Payload
|
||||
}
|
|
@ -0,0 +1,28 @@
|
|||
package com.anytypeio.anytype.domain.`object`
|
||||
|
||||
import com.anytypeio.anytype.core_models.Command
|
||||
import com.anytypeio.anytype.core_models.Id
|
||||
import com.anytypeio.anytype.core_models.InternalFlags
|
||||
import com.anytypeio.anytype.core_models.Payload
|
||||
import com.anytypeio.anytype.domain.base.AppCoroutineDispatchers
|
||||
import com.anytypeio.anytype.domain.base.ResultInteractor
|
||||
import com.anytypeio.anytype.domain.block.repo.BlockRepository
|
||||
|
||||
class SetObjectInternalFlags(
|
||||
private val repo: BlockRepository,
|
||||
dispatchers: AppCoroutineDispatchers
|
||||
) : ResultInteractor<SetObjectInternalFlags.Params, Payload>(dispatchers.io) {
|
||||
|
||||
override suspend fun doWork(params: Params): Payload {
|
||||
val command = Command.SetInternalFlags(
|
||||
ctx = params.ctx,
|
||||
flags = params.flags
|
||||
)
|
||||
return repo.setInternalFlags(command)
|
||||
}
|
||||
|
||||
data class Params(
|
||||
val ctx: Id,
|
||||
val flags: List<InternalFlags>
|
||||
)
|
||||
}
|
|
@ -25,19 +25,9 @@ class CreateObject(
|
|||
|
||||
val type = params.type ?: getDefaultPageType.run(Unit).type
|
||||
|
||||
val objectTemplates = if (type != null) {
|
||||
getTemplates.run(GetTemplates.Params(type = type))
|
||||
} else {
|
||||
null
|
||||
}
|
||||
|
||||
val internalFlags = buildList {
|
||||
if (!objectTemplates.isNullOrEmpty()) {
|
||||
add(InternalFlags.ShouldSelectType)
|
||||
add(InternalFlags.ShouldSelectTemplate)
|
||||
} else {
|
||||
add(InternalFlags.ShouldSelectType)
|
||||
}
|
||||
add(InternalFlags.ShouldSelectType)
|
||||
add(InternalFlags.ShouldSelectTemplate)
|
||||
add(InternalFlags.ShouldEmptyDelete)
|
||||
}
|
||||
|
||||
|
|
|
@ -68,13 +68,17 @@ class CreateObjectTest {
|
|||
val commands = Command.CreateObject(
|
||||
prefilled = emptyMap(),
|
||||
template = null,
|
||||
internalFlags = listOf(InternalFlags.ShouldSelectType, InternalFlags.ShouldEmptyDelete)
|
||||
internalFlags = listOf(
|
||||
InternalFlags.ShouldSelectType,
|
||||
InternalFlags.ShouldSelectTemplate,
|
||||
InternalFlags.ShouldEmptyDelete
|
||||
)
|
||||
)
|
||||
verifyBlocking(repo, times(1)) { createObject(commands) }
|
||||
}
|
||||
|
||||
@Test
|
||||
fun `when type is null and default type is note without template - should send proper params`() =
|
||||
fun `when type is null and default type is note - should send proper params`() =
|
||||
runBlocking {
|
||||
|
||||
//SETUP
|
||||
|
@ -90,12 +94,12 @@ class CreateObjectTest {
|
|||
createObject.run(params)
|
||||
|
||||
//ASSERT
|
||||
verifyBlocking(getTemplates, times(1)) { run(GetTemplates.Params(defaultType)) }
|
||||
val commands = Command.CreateObject(
|
||||
prefilled = buildMap { put(Relations.TYPE, defaultType) },
|
||||
template = null,
|
||||
internalFlags = listOf(
|
||||
InternalFlags.ShouldSelectType,
|
||||
InternalFlags.ShouldSelectTemplate,
|
||||
InternalFlags.ShouldEmptyDelete
|
||||
)
|
||||
)
|
||||
|
@ -122,7 +126,6 @@ class CreateObjectTest {
|
|||
createObject.run(params)
|
||||
|
||||
//ASSERT
|
||||
verifyBlocking(getTemplates, times(1)) { run(GetTemplates.Params(defaultType)) }
|
||||
val commands = Command.CreateObject(
|
||||
prefilled = buildMap { put(Relations.TYPE, defaultType) },
|
||||
template = null,
|
||||
|
@ -150,12 +153,12 @@ class CreateObjectTest {
|
|||
|
||||
//ASSERT
|
||||
verifyNoInteractions(getDefaultPageType)
|
||||
verifyBlocking(getTemplates, times(1)) { run(GetTemplates.Params(type)) }
|
||||
val commands = Command.CreateObject(
|
||||
prefilled = buildMap { put(Relations.TYPE, type) },
|
||||
template = null,
|
||||
internalFlags = listOf(
|
||||
InternalFlags.ShouldSelectType,
|
||||
InternalFlags.ShouldSelectTemplate,
|
||||
InternalFlags.ShouldEmptyDelete
|
||||
)
|
||||
)
|
||||
|
@ -180,7 +183,6 @@ class CreateObjectTest {
|
|||
|
||||
//ASSERT
|
||||
verifyNoInteractions(getDefaultPageType)
|
||||
verifyBlocking(getTemplates, times(1)) { run(GetTemplates.Params(type)) }
|
||||
val commands = Command.CreateObject(
|
||||
prefilled = buildMap { put(Relations.TYPE, type) },
|
||||
template = null,
|
||||
|
@ -219,7 +221,6 @@ class CreateObjectTest {
|
|||
|
||||
//ASSERT
|
||||
verifyNoInteractions(getDefaultPageType)
|
||||
verifyBlocking(getTemplates, times(1)) { run(GetTemplates.Params(type)) }
|
||||
val commands = Command.CreateObject(
|
||||
prefilled = buildMap { put(Relations.TYPE, type) },
|
||||
template = null,
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
[versions]
|
||||
middlewareVersion = "v0.27.15"
|
||||
middlewareVersion = "v0.27.20"
|
||||
kotlinVersion = '1.7.10'
|
||||
|
||||
androidxCoreVersion = "1.10.1"
|
||||
|
@ -26,7 +26,7 @@ kotlinCoroutinesVersion = '1.6.4'
|
|||
androidxTestCoreVersion = '1.5.0'
|
||||
androidxCoreTestingVersion = '2.2.0'
|
||||
androidxSecurityCryptoVersion = '1.0.0'
|
||||
androidxPreferenceVersion = '1.2.0'
|
||||
androidxPreferenceVersion = '1.2.1'
|
||||
constraintLayoutVersion = '2.1.4'
|
||||
recyclerviewVersion = '1.3.0'
|
||||
cardviewVersion = '1.0.0'
|
||||
|
|
|
@ -792,4 +792,8 @@ class BlockMiddleware(
|
|||
override suspend fun fileSpaceUsage(): FileLimits {
|
||||
return middleware.fileSpaceUsage()
|
||||
}
|
||||
|
||||
override suspend fun setInternalFlags(command: Command.SetInternalFlags): Payload {
|
||||
return middleware.setInternalFlags(command)
|
||||
}
|
||||
}
|
|
@ -12,7 +12,6 @@ class ResolveListener(
|
|||
) : NsdManager.ResolveListener {
|
||||
|
||||
override fun onResolveFailed(serviceInfo: NsdServiceInfo, errorCode: Int) {
|
||||
Timber.e("Mdns discovery resolve failed: $serviceInfo, error: $errorCode")
|
||||
try {
|
||||
semaphore.release()
|
||||
} catch (e: Exception) {
|
||||
|
|
|
@ -2185,6 +2185,20 @@ class Middleware @Inject constructor(
|
|||
return response.event.toPayload()
|
||||
}
|
||||
|
||||
@Throws(Exception::class)
|
||||
fun setInternalFlags(
|
||||
command: Command.SetInternalFlags
|
||||
): Payload {
|
||||
val request = Rpc.Object.SetInternalFlags.Request(
|
||||
contextId = command.ctx,
|
||||
internalFlags = command.flags.toMiddlewareModel()
|
||||
)
|
||||
if (BuildConfig.DEBUG) logRequest(request)
|
||||
val response = service.setInternalFlags(request)
|
||||
if (BuildConfig.DEBUG) logResponse(response)
|
||||
return response.event.toPayload()
|
||||
}
|
||||
|
||||
fun addObjectToCollection(command: Command.AddObjectToCollection): Payload {
|
||||
val request = Rpc.ObjectCollection.Add.Request(
|
||||
contextId = command.ctx,
|
||||
|
|
|
@ -143,6 +143,9 @@ interface MiddlewareService {
|
|||
@Throws(Exception::class)
|
||||
fun setObjectSource(request: Rpc.Object.SetSource.Request): Rpc.Object.SetSource.Response
|
||||
|
||||
@Throws(Exception::class)
|
||||
fun setInternalFlags(request: Rpc.Object.SetInternalFlags.Request): Rpc.Object.SetInternalFlags.Response
|
||||
|
||||
//endregion
|
||||
|
||||
//region OBJECT'S RELATIONS command
|
||||
|
|
|
@ -1611,4 +1611,17 @@ class MiddlewareServiceImplementation @Inject constructor(
|
|||
return response
|
||||
}
|
||||
}
|
||||
|
||||
override fun setInternalFlags(request: Rpc.Object.SetInternalFlags.Request): Rpc.Object.SetInternalFlags.Response {
|
||||
val encoded = Service.objectSetInternalFlags(
|
||||
Rpc.Object.SetInternalFlags.Request.ADAPTER.encode(request)
|
||||
)
|
||||
val response = Rpc.Object.SetInternalFlags.Response.ADAPTER.decode(encoded)
|
||||
val error = response.error
|
||||
if (error != null && error.code != Rpc.Object.SetInternalFlags.Response.Error.Code.NULL) {
|
||||
throw Exception(error.description)
|
||||
} else {
|
||||
return response
|
||||
}
|
||||
}
|
||||
}
|
|
@ -73,6 +73,7 @@ import com.anytypeio.anytype.domain.launch.GetDefaultPageType
|
|||
import com.anytypeio.anytype.domain.misc.UrlBuilder
|
||||
import com.anytypeio.anytype.domain.`object`.ConvertObjectToCollection
|
||||
import com.anytypeio.anytype.domain.`object`.ConvertObjectToSet
|
||||
import com.anytypeio.anytype.domain.`object`.SetObjectInternalFlags
|
||||
import com.anytypeio.anytype.domain.`object`.UpdateDetail
|
||||
import com.anytypeio.anytype.domain.objects.StoreOfObjectTypes
|
||||
import com.anytypeio.anytype.domain.objects.StoreOfRelations
|
||||
|
@ -94,6 +95,7 @@ import com.anytypeio.anytype.presentation.common.Delegator
|
|||
import com.anytypeio.anytype.presentation.common.StateReducer
|
||||
import com.anytypeio.anytype.presentation.common.SupportCommand
|
||||
import com.anytypeio.anytype.presentation.editor.ControlPanelMachine.Interactor
|
||||
import com.anytypeio.anytype.presentation.editor.ControlPanelMachine.Event.ObjectTypesWidgetEvent
|
||||
import com.anytypeio.anytype.presentation.editor.Editor.Restore
|
||||
import com.anytypeio.anytype.presentation.editor.editor.Command
|
||||
import com.anytypeio.anytype.presentation.editor.editor.Intent
|
||||
|
@ -286,7 +288,8 @@ class EditorViewModel(
|
|||
private val workspaceManager: WorkspaceManager,
|
||||
private val getObjectTypes: GetObjectTypes,
|
||||
private val interceptFileLimitEvents: InterceptFileLimitEvents,
|
||||
private val addRelationToObject: AddRelationToObject
|
||||
private val addRelationToObject: AddRelationToObject,
|
||||
private val setObjectInternalFlags: SetObjectInternalFlags
|
||||
) : ViewStateViewModel<ViewState>(),
|
||||
PickerListener,
|
||||
SupportNavigation<EventWrapper<AppNavigation.Command>>,
|
||||
|
@ -1212,9 +1215,7 @@ class EditorViewModel(
|
|||
)
|
||||
viewModelScope.launch { orchestrator.stores.views.update(new) }
|
||||
viewModelScope.launch { orchestrator.proxies.changes.send(update) }
|
||||
if (isObjectTypesWidgetVisible) {
|
||||
proceedWithHidingObjectTypeWidget()
|
||||
}
|
||||
sendHideObjectTypeWidgetEvent()
|
||||
}
|
||||
|
||||
fun onDescriptionBlockTextChanged(view: BlockView.Description) {
|
||||
|
@ -1229,9 +1230,7 @@ class EditorViewModel(
|
|||
)
|
||||
viewModelScope.launch { orchestrator.stores.views.update(new) }
|
||||
viewModelScope.launch { orchestrator.proxies.changes.send(update) }
|
||||
if (isObjectTypesWidgetVisible) {
|
||||
proceedWithHidingObjectTypeWidget()
|
||||
}
|
||||
sendHideObjectTypeWidgetEvent()
|
||||
}
|
||||
|
||||
fun onTextBlockTextChanged(view: BlockView.Text) {
|
||||
|
@ -1257,9 +1256,7 @@ class EditorViewModel(
|
|||
}
|
||||
|
||||
viewModelScope.launch { orchestrator.proxies.changes.send(update) }
|
||||
if (isObjectTypesWidgetVisible) {
|
||||
proceedWithHidingObjectTypeWidget()
|
||||
}
|
||||
sendHideObjectTypeWidgetEvent()
|
||||
}
|
||||
|
||||
fun onSelectionChanged(id: String, selection: IntRange) {
|
||||
|
@ -1438,9 +1435,7 @@ class EditorViewModel(
|
|||
) {
|
||||
Timber.d("onEndLineEnterClicked, id:[$id] text:[$text] marks:[$marks]")
|
||||
|
||||
if (isObjectTypesWidgetVisible) {
|
||||
proceedWithHidingObjectTypeWidget()
|
||||
}
|
||||
sendHideObjectTypeWidgetEvent()
|
||||
|
||||
val target = blocks.first { it.id == id }
|
||||
|
||||
|
@ -2908,9 +2903,7 @@ class EditorViewModel(
|
|||
fun onOutsideClicked() {
|
||||
Timber.d("onOutsideClicked, ")
|
||||
|
||||
if (isObjectTypesWidgetVisible) {
|
||||
proceedWithHidingObjectTypeWidget()
|
||||
}
|
||||
sendHideObjectTypeWidgetEvent()
|
||||
|
||||
if (mode is EditorMode.Styling) {
|
||||
onExitBlockStyleToolbarClicked()
|
||||
|
@ -4289,11 +4282,9 @@ class EditorViewModel(
|
|||
analytics = analytics,
|
||||
objType = storeOfObjectTypes.get(type)
|
||||
)
|
||||
if (isObjectTypesWidgetVisible) {
|
||||
proceedWithHidingObjectTypeWidget()
|
||||
}
|
||||
sendHideObjectTypeWidgetEvent()
|
||||
if (applyTemplate) {
|
||||
proceedWithTemplateSelection(type)
|
||||
proceedWithCheckingInternalFlagShouldSelectTemplate(objTypeId = type)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -5353,9 +5344,7 @@ class EditorViewModel(
|
|||
Timber.d("onKeyPressedEvent, event:[$event]")
|
||||
when (event) {
|
||||
is KeyPressedEvent.OnTitleBlockEnterKeyEvent -> {
|
||||
if (isObjectTypesWidgetVisible) {
|
||||
proceedWithHidingObjectTypeWidget()
|
||||
}
|
||||
sendHideObjectTypeWidgetEvent()
|
||||
proceedWithTitleEnterClicked(
|
||||
title = event.target,
|
||||
text = event.text,
|
||||
|
@ -5883,28 +5872,17 @@ class EditorViewModel(
|
|||
|
||||
fun onObjectTypesWidgetDoneClicked() {
|
||||
Timber.d("onObjectTypesWidgetDoneClicked, ")
|
||||
proceedWithHidingObjectTypeWidget()
|
||||
val details = orchestrator.stores.details.current()
|
||||
val wrapper = ObjectWrapper.Basic(details.details[context]?.map ?: emptyMap())
|
||||
if (wrapper.internalFlags.contains(InternalFlags.ShouldSelectTemplate)) {
|
||||
if (wrapper.type.isNotEmpty()) {
|
||||
proceedWithTemplateSelection(typeId = wrapper.type.first())
|
||||
}
|
||||
}
|
||||
sendHideObjectTypeWidgetEvent()
|
||||
proceedWithCheckingInternalFlagShouldSelectTemplate()
|
||||
}
|
||||
|
||||
private fun proceedWithShowingObjectTypesWidget() {
|
||||
val restrictions = orchestrator.stores.objectRestrictions.current()
|
||||
if (restrictions.contains(ObjectRestriction.TYPE_CHANGE)) {
|
||||
Timber.d("proceedWithShowingObjectTypesWidget, type change is restricted")
|
||||
return
|
||||
}
|
||||
val details = orchestrator.stores.details.current()
|
||||
val objectDetails = ObjectWrapper.Basic(details.details[context]?.map ?: emptyMap())
|
||||
|
||||
val internalFlags = objectDetails.internalFlags
|
||||
if (internalFlags.contains(InternalFlags.ShouldSelectType)) {
|
||||
proceedWithGettingObjectTypesForObjectTypeWidget()
|
||||
}
|
||||
proceedWithCheckingInternalFlagShouldSelectType()
|
||||
}
|
||||
|
||||
private fun proceedWithGettingObjectTypesForObjectTypeWidget() {
|
||||
|
@ -5959,10 +5937,6 @@ class EditorViewModel(
|
|||
)
|
||||
}
|
||||
|
||||
private fun proceedWithHidingObjectTypeWidget() {
|
||||
controlPanelInteractor.onEvent(ControlPanelMachine.Event.ObjectTypesWidgetEvent.Hide)
|
||||
}
|
||||
|
||||
private fun proceedWithOpeningSelectingObjectTypeScreen() {
|
||||
val excludeTypes = orchestrator.stores.details.current().details[context]?.type
|
||||
val command = if (isObjectTypesWidgetVisible) {
|
||||
|
@ -5976,6 +5950,10 @@ class EditorViewModel(
|
|||
}
|
||||
dispatch(command)
|
||||
}
|
||||
|
||||
private fun sendHideObjectTypeWidgetEvent() {
|
||||
if (isObjectTypesWidgetVisible) controlPanelInteractor.onEvent(ObjectTypesWidgetEvent.Hide)
|
||||
}
|
||||
//endregion
|
||||
|
||||
//region OBJECT APPEARANCE SETTING
|
||||
|
@ -6186,23 +6164,28 @@ class EditorViewModel(
|
|||
viewModelScope.launch { onEvent(SelectTemplateEvent.OnSkipped) }
|
||||
}
|
||||
|
||||
private fun proceedWithTemplateSelection(typeId: Id) {
|
||||
private fun proceedWithStartTemplateEvent(objTypeId: Id) {
|
||||
viewModelScope.launch {
|
||||
val objType = storeOfObjectTypes.get(typeId)
|
||||
val objType = storeOfObjectTypes.get(objTypeId)
|
||||
if (objType != null) {
|
||||
onEvent(
|
||||
SelectTemplateEvent.OnStart(
|
||||
ctx = context,
|
||||
type = typeId,
|
||||
type = objTypeId,
|
||||
typeName = objType.name.orEmpty()
|
||||
)
|
||||
)
|
||||
} else {
|
||||
Timber.e("Error while getting object type from storeOfObjectTypes by id: $typeId")
|
||||
Timber.e("Error while getting object type from storeOfObjectTypes by id: $objTypeId")
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private fun getObjectTypeFromDetails(): Id? {
|
||||
val details = orchestrator.stores.details.current()
|
||||
val wrapper = ObjectWrapper.Basic(details.details[context]?.map ?: emptyMap())
|
||||
return wrapper.getProperType()
|
||||
}
|
||||
//endregion
|
||||
|
||||
//region SIMPLE TABLES
|
||||
|
@ -6892,6 +6875,84 @@ class EditorViewModel(
|
|||
}
|
||||
}
|
||||
//endregion
|
||||
|
||||
//region INTERNAL FLAGS
|
||||
private fun proceedWithCheckingInternalFlagShouldSelectType() {
|
||||
val internalFlags = getInternalFlagsFromDetails()
|
||||
if (internalFlags.contains(InternalFlags.ShouldSelectType)) {
|
||||
//We use this flag to show object type widget and then we don't need it anymore
|
||||
proceedWithGettingObjectTypesForObjectTypeWidget()
|
||||
proceedWithOptOutTypeInternalFlag()
|
||||
} else {
|
||||
Timber.d("Object doesn't have internal flag: ShouldSelectType")
|
||||
}
|
||||
}
|
||||
|
||||
private fun proceedWithCheckingInternalFlagShouldSelectTemplate(objTypeId: Id? = null) {
|
||||
val internalFlags = getInternalFlagsFromDetails()
|
||||
if (internalFlags.contains(InternalFlags.ShouldSelectTemplate)) {
|
||||
//We use this flag to show template widget and then we don't need it anymore
|
||||
val properObjTypeId = objTypeId ?: getObjectTypeFromDetails() ?: return
|
||||
proceedWithStartTemplateEvent(objTypeId = properObjTypeId)
|
||||
proceedWithOptOutTemplateInternalFlag()
|
||||
} else {
|
||||
Timber.d("Object doesn't have internal flag: ShouldSelectTemplate")
|
||||
}
|
||||
}
|
||||
|
||||
private fun proceedWithOptOutTypeInternalFlag() {
|
||||
val internalFlags = getInternalFlagsFromDetails()
|
||||
if (!internalFlags.contains(InternalFlags.ShouldSelectType)) return
|
||||
val flagsWithoutType = filterOutInternalFlags(
|
||||
flags = internalFlags,
|
||||
out = InternalFlags.ShouldSelectType
|
||||
)
|
||||
updateFlagsAndProceed(
|
||||
flags = flagsWithoutType,
|
||||
action = this::sendHideObjectTypeWidgetEvent
|
||||
)
|
||||
}
|
||||
|
||||
private fun proceedWithOptOutTemplateInternalFlag() {
|
||||
val internalFlags = getInternalFlagsFromDetails()
|
||||
if (!internalFlags.contains(InternalFlags.ShouldSelectTemplate)) return
|
||||
val flagsWithoutTemplate = filterOutInternalFlags(
|
||||
flags = internalFlags,
|
||||
out = InternalFlags.ShouldSelectTemplate
|
||||
)
|
||||
updateFlagsAndProceed(flags = flagsWithoutTemplate)
|
||||
}
|
||||
|
||||
private fun getInternalFlagsFromDetails(): List<InternalFlags> {
|
||||
val details = orchestrator.stores.details.current()
|
||||
val obj = ObjectWrapper.Basic(details.details[context]?.map ?: emptyMap())
|
||||
return obj.internalFlags
|
||||
}
|
||||
|
||||
private fun filterOutInternalFlags(flags: List<InternalFlags>, out: InternalFlags): List<InternalFlags> {
|
||||
return flags.filter { it != out }
|
||||
}
|
||||
|
||||
private fun updateFlagsAndProceed(flags: List<InternalFlags>, action: () -> Unit = {}) {
|
||||
viewModelScope.launch {
|
||||
val params = SetObjectInternalFlags.Params(
|
||||
ctx = context,
|
||||
flags = flags
|
||||
)
|
||||
setObjectInternalFlags.async(params).fold(
|
||||
onSuccess = {
|
||||
dispatcher.send(it)
|
||||
Timber.d("Internal flags updated")
|
||||
action.invoke()
|
||||
},
|
||||
onFailure = {
|
||||
Timber.e(it, "Error while updating internal flags")
|
||||
action.invoke()
|
||||
}
|
||||
)
|
||||
}
|
||||
}
|
||||
//endregion
|
||||
}
|
||||
|
||||
private const val NO_POSITION = -1
|
||||
|
|
|
@ -18,6 +18,7 @@ import com.anytypeio.anytype.domain.launch.GetDefaultPageType
|
|||
import com.anytypeio.anytype.domain.misc.UrlBuilder
|
||||
import com.anytypeio.anytype.domain.`object`.ConvertObjectToCollection
|
||||
import com.anytypeio.anytype.domain.`object`.ConvertObjectToSet
|
||||
import com.anytypeio.anytype.domain.`object`.SetObjectInternalFlags
|
||||
import com.anytypeio.anytype.domain.`object`.UpdateDetail
|
||||
import com.anytypeio.anytype.domain.objects.StoreOfObjectTypes
|
||||
import com.anytypeio.anytype.domain.objects.StoreOfRelations
|
||||
|
@ -79,7 +80,8 @@ open class EditorViewModelFactory(
|
|||
private val getObjectTypes: GetObjectTypes,
|
||||
private val objectToCollection: ConvertObjectToCollection,
|
||||
private val interceptFileLimitEvents: InterceptFileLimitEvents,
|
||||
private val addRelationToObject: AddRelationToObject
|
||||
private val addRelationToObject: AddRelationToObject,
|
||||
private val setObjectInternalFlags: SetObjectInternalFlags
|
||||
) : ViewModelProvider.Factory {
|
||||
|
||||
@Suppress("UNCHECKED_CAST")
|
||||
|
@ -120,7 +122,8 @@ open class EditorViewModelFactory(
|
|||
workspaceManager = workspaceManager,
|
||||
getObjectTypes = getObjectTypes,
|
||||
interceptFileLimitEvents = interceptFileLimitEvents,
|
||||
addRelationToObject = addRelationToObject
|
||||
addRelationToObject = addRelationToObject,
|
||||
setObjectInternalFlags = setObjectInternalFlags
|
||||
) as T
|
||||
}
|
||||
}
|
|
@ -8,6 +8,7 @@ import com.anytypeio.anytype.analytics.base.EventsDictionary.addView
|
|||
import com.anytypeio.anytype.analytics.base.EventsDictionary.changeFilterValue
|
||||
import com.anytypeio.anytype.analytics.base.EventsDictionary.changeSortValue
|
||||
import com.anytypeio.anytype.analytics.base.EventsDictionary.changeViewType
|
||||
import com.anytypeio.anytype.analytics.base.EventsDictionary.clickNewOption
|
||||
import com.anytypeio.anytype.analytics.base.EventsDictionary.collectionScreenShow
|
||||
import com.anytypeio.anytype.analytics.base.EventsDictionary.duplicateView
|
||||
import com.anytypeio.anytype.analytics.base.EventsDictionary.objectCreate
|
||||
|
@ -18,6 +19,7 @@ import com.anytypeio.anytype.analytics.base.EventsDictionary.removeFilter
|
|||
import com.anytypeio.anytype.analytics.base.EventsDictionary.removeSort
|
||||
import com.anytypeio.anytype.analytics.base.EventsDictionary.removeView
|
||||
import com.anytypeio.anytype.analytics.base.EventsDictionary.repositionView
|
||||
import com.anytypeio.anytype.analytics.base.EventsDictionary.selectTemplate
|
||||
import com.anytypeio.anytype.analytics.base.EventsDictionary.setScreenShow
|
||||
import com.anytypeio.anytype.analytics.base.EventsDictionary.setSelectQuery
|
||||
import com.anytypeio.anytype.analytics.base.EventsDictionary.switchView
|
||||
|
@ -1201,6 +1203,37 @@ fun CoroutineScope.logEvent(
|
|||
)
|
||||
)
|
||||
}
|
||||
|
||||
ObjectStateAnalyticsEvent.SELECT_TEMPLATE -> {
|
||||
val route = when (state) {
|
||||
is ObjectState.DataView.Collection -> EventsDictionary.Routes.objCreateCollection
|
||||
is ObjectState.DataView.Set -> EventsDictionary.Routes.objCreateSet
|
||||
}
|
||||
scope.sendEvent(
|
||||
analytics = analytics,
|
||||
eventName = selectTemplate,
|
||||
startTime = startTime,
|
||||
middleTime = middleTime,
|
||||
props = buildProps(
|
||||
route = route
|
||||
)
|
||||
)
|
||||
}
|
||||
ObjectStateAnalyticsEvent.SHOW_TEMPLATES -> {
|
||||
val route = when (state) {
|
||||
is ObjectState.DataView.Collection -> EventsDictionary.Routes.objCreateCollection
|
||||
is ObjectState.DataView.Set -> EventsDictionary.Routes.objCreateSet
|
||||
}
|
||||
scope.sendEvent(
|
||||
analytics = analytics,
|
||||
eventName = clickNewOption,
|
||||
startTime = startTime,
|
||||
middleTime = middleTime,
|
||||
props = buildProps(
|
||||
route = route
|
||||
)
|
||||
)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -1242,7 +1275,9 @@ enum class ObjectStateAnalyticsEvent {
|
|||
ADD_SORT,
|
||||
CHANGE_SORT_VALUE,
|
||||
REMOVE_SORT,
|
||||
OBJECT_CREATE
|
||||
OBJECT_CREATE,
|
||||
SELECT_TEMPLATE,
|
||||
SHOW_TEMPLATES
|
||||
}
|
||||
|
||||
fun CoroutineScope.sendEditWidgetsEvent(
|
||||
|
@ -1681,4 +1716,18 @@ fun CoroutineScope.sendAnalyticsOnboardingLoginEvent(
|
|||
}
|
||||
)
|
||||
)
|
||||
}
|
||||
|
||||
fun CoroutineScope.sendAnalyticsSelectTemplateEvent(
|
||||
analytics: Analytics
|
||||
) {
|
||||
sendEvent(
|
||||
analytics = analytics,
|
||||
eventName = selectTemplate,
|
||||
props = Props(
|
||||
buildMap {
|
||||
put(EventsPropertiesKey.route, "Navigation")
|
||||
}
|
||||
)
|
||||
)
|
||||
}
|
|
@ -35,6 +35,9 @@ class OnboardingSoulCreationViewModel @Inject constructor(
|
|||
val config = configStorage.getOrNull()
|
||||
if (config != null) {
|
||||
viewModelScope.launch {
|
||||
sendAnalyticsOnboardingScreenEvent(analytics,
|
||||
EventsDictionary.ScreenOnboardingStep.SOUL_CREATING
|
||||
)
|
||||
setObjectDetails.async(
|
||||
SetObjectDetails.Params(
|
||||
ctx = config.profile, details = mapOf(Relations.NAME to name)
|
||||
|
@ -59,6 +62,10 @@ class OnboardingSoulCreationViewModel @Inject constructor(
|
|||
val config = configStorage.getOrNull()
|
||||
if (config != null) {
|
||||
viewModelScope.launch {
|
||||
sendAnalyticsOnboardingScreenEvent(
|
||||
analytics = analytics,
|
||||
step = EventsDictionary.ScreenOnboardingStep.SPACE_CREATING
|
||||
)
|
||||
setObjectDetails.async(
|
||||
SetObjectDetails.Params(
|
||||
ctx = config.workspace,
|
||||
|
@ -69,10 +76,6 @@ class OnboardingSoulCreationViewModel @Inject constructor(
|
|||
Timber.e(it, "Error while updating object details")
|
||||
},
|
||||
onSuccess = {
|
||||
sendAnalyticsOnboardingScreenEvent(
|
||||
analytics = analytics,
|
||||
step = EventsDictionary.ScreenOnboardingStep.SPACE_CREATING
|
||||
)
|
||||
_navigationFlow.emit(Navigation.OpenSoulCreationAnim(name))
|
||||
}
|
||||
)
|
||||
|
@ -88,12 +91,6 @@ class OnboardingSoulCreationViewModel @Inject constructor(
|
|||
viewModelScope.launch { toasts.emit(msg) }
|
||||
}
|
||||
|
||||
fun sendAnalyticsOnboardingScreen() {
|
||||
viewModelScope.sendAnalyticsOnboardingScreenEvent(analytics,
|
||||
EventsDictionary.ScreenOnboardingStep.SOUL_CREATING
|
||||
)
|
||||
}
|
||||
|
||||
sealed interface Navigation {
|
||||
class OpenSoulCreationAnim(val name: String): Navigation
|
||||
}
|
||||
|
|
|
@ -446,4 +446,11 @@ fun ObjectWrapper.Basic.toTemplateViewBlank(typeId: Id): TemplateView.Blank {
|
|||
typeId = typeId,
|
||||
layout = layout?.code ?: ObjectType.Layout.BASIC.code
|
||||
)
|
||||
}
|
||||
|
||||
fun ObjectWrapper.Type.toTemplateViewBlank(): TemplateView.Blank {
|
||||
return TemplateView.Blank(
|
||||
typeId = id,
|
||||
layout = recommendedLayout?.code ?: ObjectType.Layout.BASIC.code
|
||||
)
|
||||
}
|
|
@ -539,24 +539,22 @@ class ObjectSetViewModel(
|
|||
query.isEmpty() || setOfValue.isEmpty() -> DataViewViewState.Set.NoQuery
|
||||
render == null -> DataViewViewState.Set.NoView
|
||||
render.isEmpty() -> {
|
||||
val isTemplatesAllowed = templates.isNotEmpty() &&
|
||||
objectState.isTemplatesAllowed(
|
||||
setOfValue,
|
||||
storeOfObjectTypes,
|
||||
getDefaultPageType
|
||||
)
|
||||
val isTemplatesAllowed = objectState.isTemplatesAllowed(
|
||||
setOfValue,
|
||||
storeOfObjectTypes,
|
||||
getDefaultPageType
|
||||
)
|
||||
DataViewViewState.Set.NoItems(
|
||||
title = render.title,
|
||||
hasTemplates = isTemplatesAllowed
|
||||
)
|
||||
}
|
||||
else -> {
|
||||
val isTemplatesAllowed = templates.isNotEmpty() &&
|
||||
objectState.isTemplatesAllowed(
|
||||
setOfValue,
|
||||
storeOfObjectTypes,
|
||||
getDefaultPageType
|
||||
)
|
||||
val isTemplatesAllowed = objectState.isTemplatesAllowed(
|
||||
setOfValue,
|
||||
storeOfObjectTypes,
|
||||
getDefaultPageType
|
||||
)
|
||||
DataViewViewState.Set.Default(
|
||||
viewer = render,
|
||||
hasTemplates = isTemplatesAllowed
|
||||
|
@ -882,6 +880,14 @@ class ObjectSetViewModel(
|
|||
items = _templateViews.value,
|
||||
showWidget = true
|
||||
)
|
||||
viewModelScope.launch {
|
||||
logEvent(
|
||||
state = stateReducer.state.value,
|
||||
analytics = analytics,
|
||||
event = ObjectStateAnalyticsEvent.SHOW_TEMPLATES
|
||||
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
fun onDismissTemplatesWidget() {
|
||||
|
@ -1494,6 +1500,8 @@ class ObjectSetViewModel(
|
|||
_templateViews.value =
|
||||
listOf(templates.first().toTemplateViewBlank(objectType.id)) +
|
||||
templates.map { it.toTemplateView(typeId = objectType.id) }
|
||||
} else {
|
||||
_templateViews.value = listOf(objectType.toTemplateViewBlank())
|
||||
}
|
||||
},
|
||||
onFailure = { e ->
|
||||
|
@ -1519,10 +1527,24 @@ class ObjectSetViewModel(
|
|||
when(item) {
|
||||
is TemplateView.Blank -> {
|
||||
templatesWidgetState.value = TemplatesWidgetUiState.empty()
|
||||
viewModelScope.launch {
|
||||
logEvent(
|
||||
state = stateReducer.state.value,
|
||||
analytics = analytics,
|
||||
event = ObjectStateAnalyticsEvent.SELECT_TEMPLATE
|
||||
)
|
||||
}
|
||||
proceedWithCreatingNewDataViewObject()
|
||||
}
|
||||
is TemplateView.Template -> {
|
||||
templatesWidgetState.value = TemplatesWidgetUiState.empty()
|
||||
viewModelScope.launch {
|
||||
logEvent(
|
||||
state = stateReducer.state.value,
|
||||
analytics = analytics,
|
||||
event = ObjectStateAnalyticsEvent.SELECT_TEMPLATE
|
||||
)
|
||||
}
|
||||
proceedWithCreatingNewDataViewObject(templatesId = item.id)
|
||||
}
|
||||
}
|
||||
|
|
|
@ -4,6 +4,7 @@ import androidx.lifecycle.MutableLiveData
|
|||
import androidx.lifecycle.ViewModel
|
||||
import androidx.lifecycle.ViewModelProvider
|
||||
import androidx.lifecycle.viewModelScope
|
||||
import com.anytypeio.anytype.analytics.base.Analytics
|
||||
import com.anytypeio.anytype.core_models.Id
|
||||
import com.anytypeio.anytype.core_models.ObjectType
|
||||
import com.anytypeio.anytype.core_models.ObjectWrapper
|
||||
|
@ -13,6 +14,7 @@ import com.anytypeio.anytype.domain.objects.StoreOfObjectTypes
|
|||
import com.anytypeio.anytype.domain.templates.ApplyTemplate
|
||||
import com.anytypeio.anytype.domain.templates.GetTemplates
|
||||
import com.anytypeio.anytype.presentation.common.BaseViewModel
|
||||
import com.anytypeio.anytype.presentation.extension.sendAnalyticsSelectTemplateEvent
|
||||
import com.anytypeio.anytype.presentation.navigation.AppNavigation
|
||||
import com.anytypeio.anytype.presentation.navigation.SupportNavigation
|
||||
import kotlinx.coroutines.launch
|
||||
|
@ -24,7 +26,8 @@ import timber.log.Timber
|
|||
class TemplateSelectViewModel(
|
||||
private val storeOfObjectTypes: StoreOfObjectTypes,
|
||||
private val getTemplates: GetTemplates,
|
||||
private val applyTemplate: ApplyTemplate
|
||||
private val applyTemplate: ApplyTemplate,
|
||||
private val analytics: Analytics
|
||||
) : BaseViewModel(), SupportNavigation<EventWrapper<AppNavigation.Command>> {
|
||||
|
||||
val isDismissed = MutableStateFlow(false)
|
||||
|
@ -102,6 +105,9 @@ class TemplateSelectViewModel(
|
|||
proceedWithApplyingTemplate(ctx, template)
|
||||
}
|
||||
}
|
||||
viewModelScope.launch {
|
||||
sendAnalyticsSelectTemplateEvent(analytics)
|
||||
}
|
||||
}
|
||||
else -> {
|
||||
Timber.e("onUseTemplate: unexpected state $state")
|
||||
|
@ -127,10 +133,15 @@ class TemplateSelectViewModel(
|
|||
}
|
||||
}
|
||||
|
||||
fun onSkipButtonClicked() {
|
||||
isDismissed.value = true
|
||||
}
|
||||
|
||||
class Factory @Inject constructor(
|
||||
private val applyTemplate: ApplyTemplate,
|
||||
private val getTemplates: GetTemplates,
|
||||
private val storeOfObjectTypes: StoreOfObjectTypes
|
||||
private val storeOfObjectTypes: StoreOfObjectTypes,
|
||||
private val analytics: Analytics
|
||||
) : ViewModelProvider.Factory {
|
||||
|
||||
@Suppress("UNCHECKED_CAST")
|
||||
|
@ -138,7 +149,8 @@ class TemplateSelectViewModel(
|
|||
return TemplateSelectViewModel(
|
||||
applyTemplate = applyTemplate,
|
||||
getTemplates = getTemplates,
|
||||
storeOfObjectTypes = storeOfObjectTypes
|
||||
storeOfObjectTypes = storeOfObjectTypes,
|
||||
analytics = analytics
|
||||
) as T
|
||||
}
|
||||
}
|
||||
|
@ -149,7 +161,6 @@ class TemplateSelectViewModel(
|
|||
) : ViewState()
|
||||
|
||||
object Init : ViewState()
|
||||
object ErrorGettingType : ViewState()
|
||||
}
|
||||
|
||||
}
|
|
@ -61,6 +61,7 @@ import com.anytypeio.anytype.domain.launch.GetDefaultPageType
|
|||
import com.anytypeio.anytype.domain.misc.UrlBuilder
|
||||
import com.anytypeio.anytype.domain.`object`.ConvertObjectToCollection
|
||||
import com.anytypeio.anytype.domain.`object`.ConvertObjectToSet
|
||||
import com.anytypeio.anytype.domain.`object`.SetObjectInternalFlags
|
||||
import com.anytypeio.anytype.domain.`object`.UpdateDetail
|
||||
import com.anytypeio.anytype.domain.objects.DefaultStoreOfObjectTypes
|
||||
import com.anytypeio.anytype.domain.objects.DefaultStoreOfRelations
|
||||
|
@ -352,6 +353,7 @@ open class EditorViewModelTest {
|
|||
private lateinit var objectToSet: ConvertObjectToSet
|
||||
private lateinit var clearBlockContent: ClearBlockContent
|
||||
private lateinit var clearBlockStyle: ClearBlockStyle
|
||||
private lateinit var setObjectInternalFlags: SetObjectInternalFlags
|
||||
|
||||
val root = MockDataFactory.randomUuid()
|
||||
|
||||
|
@ -3812,6 +3814,7 @@ open class EditorViewModelTest {
|
|||
clearBlockContent = ClearBlockContent(repo)
|
||||
clearBlockStyle = ClearBlockStyle(repo)
|
||||
interceptFileLimitEvents = InterceptFileLimitEvents(fileLimitsEventChannel, dispatchers)
|
||||
setObjectInternalFlags = SetObjectInternalFlags(repo, dispatchers)
|
||||
|
||||
workspaceManager = WorkspaceManager.DefaultWorkspaceManager()
|
||||
runBlocking {
|
||||
|
@ -3904,7 +3907,8 @@ open class EditorViewModelTest {
|
|||
workspaceManager = workspaceManager,
|
||||
getObjectTypes = getObjectTypes,
|
||||
interceptFileLimitEvents = interceptFileLimitEvents,
|
||||
addRelationToObject = addRelationToObject
|
||||
addRelationToObject = addRelationToObject,
|
||||
setObjectInternalFlags = setObjectInternalFlags
|
||||
)
|
||||
}
|
||||
|
||||
|
|
|
@ -10,6 +10,7 @@ import com.anytypeio.anytype.core_models.Relations
|
|||
import com.anytypeio.anytype.core_models.StubHeader
|
||||
import com.anytypeio.anytype.core_models.StubSmartBlock
|
||||
import com.anytypeio.anytype.core_models.StubTitle
|
||||
import com.anytypeio.anytype.domain.`object`.SetObjectInternalFlags
|
||||
import com.anytypeio.anytype.presentation.util.DefaultCoroutineTestRule
|
||||
import kotlin.test.assertEquals
|
||||
import kotlinx.coroutines.ExperimentalCoroutinesApi
|
||||
|
@ -19,6 +20,10 @@ import org.junit.Before
|
|||
import org.junit.Rule
|
||||
import org.junit.Test
|
||||
import org.mockito.MockitoAnnotations
|
||||
import org.mockito.kotlin.times
|
||||
import org.mockito.kotlin.verifyBlocking
|
||||
import org.mockito.kotlin.verifyNoInteractions
|
||||
import org.mockito.kotlin.verifyNoMoreInteractions
|
||||
|
||||
@ExperimentalCoroutinesApi
|
||||
class EditorInternalFlagsTest : EditorPresentationTestSetup() {
|
||||
|
@ -99,4 +104,203 @@ class EditorInternalFlagsTest : EditorPresentationTestSetup() {
|
|||
|
||||
assertEquals(expected = expectedFlags, actual = actualFlags)
|
||||
}
|
||||
|
||||
@Test
|
||||
fun `should remove type flag on show object event with type flag in details`() = runTest {
|
||||
val title = StubTitle()
|
||||
val header = StubHeader(children = listOf(title.id))
|
||||
val page = StubSmartBlock(id = root, children = listOf(header.id))
|
||||
val document = listOf(page, header, title)
|
||||
stubInterceptEvents()
|
||||
|
||||
val detailsList = Block.Details(
|
||||
details = mapOf(
|
||||
root to Block.Fields(
|
||||
mapOf(
|
||||
Relations.TYPE to ObjectTypeIds.PAGE,
|
||||
Relations.LAYOUT to ObjectType.Layout.BASIC.code.toDouble(),
|
||||
Relations.INTERNAL_FLAGS to listOf(
|
||||
InternalFlags.ShouldSelectTemplate.code.toDouble(),
|
||||
InternalFlags.ShouldEmptyDelete.code.toDouble(),
|
||||
InternalFlags.ShouldSelectType.code.toDouble(),
|
||||
)
|
||||
)
|
||||
)
|
||||
)
|
||||
)
|
||||
stubOpenDocument(document = document, details = detailsList)
|
||||
stubGetObjectTypes(types = emptyList())
|
||||
stubGetDefaultObjectType()
|
||||
|
||||
val vm = buildViewModel()
|
||||
|
||||
stubFileLimitEvents()
|
||||
stubSetInternalFlags()
|
||||
|
||||
vm.onStart(root)
|
||||
|
||||
advanceUntilIdle()
|
||||
|
||||
verifyBlocking(setObjectInternalFlags, times(1)) {
|
||||
async(
|
||||
params = SetObjectInternalFlags.Params(
|
||||
ctx = root,
|
||||
flags = listOf(
|
||||
InternalFlags.ShouldSelectTemplate,
|
||||
InternalFlags.ShouldEmptyDelete
|
||||
)
|
||||
)
|
||||
)
|
||||
}
|
||||
|
||||
coroutineTestRule.advanceTime(100)
|
||||
}
|
||||
|
||||
@Test
|
||||
fun `should not remove type flag on show object event without type flag in details`() = runTest {
|
||||
val title = StubTitle()
|
||||
val header = StubHeader(children = listOf(title.id))
|
||||
val page = StubSmartBlock(id = root, children = listOf(header.id))
|
||||
val document = listOf(page, header, title)
|
||||
stubInterceptEvents()
|
||||
|
||||
val detailsList = Block.Details(
|
||||
details = mapOf(
|
||||
root to Block.Fields(
|
||||
mapOf(
|
||||
Relations.TYPE to ObjectTypeIds.PAGE,
|
||||
Relations.LAYOUT to ObjectType.Layout.BASIC.code.toDouble(),
|
||||
Relations.INTERNAL_FLAGS to listOf(
|
||||
InternalFlags.ShouldSelectTemplate.code.toDouble(),
|
||||
InternalFlags.ShouldEmptyDelete.code.toDouble()
|
||||
)
|
||||
)
|
||||
)
|
||||
)
|
||||
)
|
||||
stubOpenDocument(document = document, details = detailsList)
|
||||
stubGetObjectTypes(types = emptyList())
|
||||
stubGetDefaultObjectType()
|
||||
|
||||
val vm = buildViewModel()
|
||||
|
||||
stubFileLimitEvents()
|
||||
stubSetInternalFlags()
|
||||
|
||||
vm.onStart(root)
|
||||
|
||||
advanceUntilIdle()
|
||||
|
||||
verifyNoInteractions(setObjectInternalFlags)
|
||||
|
||||
coroutineTestRule.advanceTime(100)
|
||||
}
|
||||
|
||||
@Test
|
||||
fun `should remove template flag on start template selection widget`() = runTest {
|
||||
val title = StubTitle()
|
||||
val header = StubHeader(children = listOf(title.id))
|
||||
val page = StubSmartBlock(id = root, children = listOf(header.id))
|
||||
val document = listOf(page, header, title)
|
||||
stubInterceptEvents()
|
||||
|
||||
val detailsList = Block.Details(
|
||||
details = mapOf(
|
||||
root to Block.Fields(
|
||||
mapOf(
|
||||
Relations.TYPE to ObjectTypeIds.PAGE,
|
||||
Relations.LAYOUT to ObjectType.Layout.BASIC.code.toDouble(),
|
||||
Relations.INTERNAL_FLAGS to listOf(
|
||||
InternalFlags.ShouldSelectTemplate.code.toDouble(),
|
||||
InternalFlags.ShouldEmptyDelete.code.toDouble(),
|
||||
)
|
||||
)
|
||||
)
|
||||
)
|
||||
)
|
||||
stubOpenDocument(document = document, details = detailsList)
|
||||
stubGetObjectTypes(types = emptyList())
|
||||
stubGetDefaultObjectType()
|
||||
|
||||
val vm = buildViewModel()
|
||||
|
||||
stubFileLimitEvents()
|
||||
stubSetInternalFlags()
|
||||
|
||||
vm.onStart(root)
|
||||
|
||||
advanceUntilIdle()
|
||||
vm.onObjectTypesWidgetDoneClicked()
|
||||
|
||||
advanceUntilIdle()
|
||||
|
||||
verifyBlocking(setObjectInternalFlags, times(1)) {
|
||||
async(
|
||||
params = SetObjectInternalFlags.Params(
|
||||
ctx = root,
|
||||
flags = listOf(
|
||||
InternalFlags.ShouldEmptyDelete
|
||||
)
|
||||
)
|
||||
)
|
||||
}
|
||||
|
||||
coroutineTestRule.advanceTime(100)
|
||||
}
|
||||
|
||||
@Test
|
||||
fun `should not remove template flag on start template selection widget when flag isn't present`() = runTest {
|
||||
val title = StubTitle()
|
||||
val header = StubHeader(children = listOf(title.id))
|
||||
val page = StubSmartBlock(id = root, children = listOf(header.id))
|
||||
val document = listOf(page, header, title)
|
||||
stubInterceptEvents()
|
||||
|
||||
val detailsList = Block.Details(
|
||||
details = mapOf(
|
||||
root to Block.Fields(
|
||||
mapOf(
|
||||
Relations.TYPE to ObjectTypeIds.PAGE,
|
||||
Relations.LAYOUT to ObjectType.Layout.BASIC.code.toDouble(),
|
||||
Relations.INTERNAL_FLAGS to listOf(
|
||||
InternalFlags.ShouldSelectType.code.toDouble(),
|
||||
InternalFlags.ShouldEmptyDelete.code.toDouble(),
|
||||
)
|
||||
)
|
||||
)
|
||||
)
|
||||
)
|
||||
stubOpenDocument(document = document, details = detailsList)
|
||||
stubGetObjectTypes(types = emptyList())
|
||||
stubGetDefaultObjectType()
|
||||
|
||||
val vm = buildViewModel()
|
||||
|
||||
stubFileLimitEvents()
|
||||
stubSetInternalFlags()
|
||||
|
||||
vm.onStart(root)
|
||||
|
||||
advanceUntilIdle()
|
||||
vm.onObjectTypesWidgetDoneClicked()
|
||||
|
||||
advanceUntilIdle()
|
||||
|
||||
verifyBlocking(setObjectInternalFlags, times(1)) {
|
||||
async(
|
||||
params = SetObjectInternalFlags.Params(
|
||||
ctx = root,
|
||||
flags = listOf(
|
||||
InternalFlags.ShouldEmptyDelete
|
||||
)
|
||||
)
|
||||
)
|
||||
}
|
||||
|
||||
advanceUntilIdle()
|
||||
|
||||
verifyNoMoreInteractions(setObjectInternalFlags)
|
||||
|
||||
coroutineTestRule.advanceTime(100)
|
||||
}
|
||||
}
|
|
@ -50,6 +50,7 @@ import com.anytypeio.anytype.domain.launch.GetDefaultPageType
|
|||
import com.anytypeio.anytype.domain.misc.UrlBuilder
|
||||
import com.anytypeio.anytype.domain.`object`.ConvertObjectToCollection
|
||||
import com.anytypeio.anytype.domain.`object`.ConvertObjectToSet
|
||||
import com.anytypeio.anytype.domain.`object`.SetObjectInternalFlags
|
||||
import com.anytypeio.anytype.domain.`object`.UpdateDetail
|
||||
import com.anytypeio.anytype.domain.objects.DefaultStoreOfObjectTypes
|
||||
import com.anytypeio.anytype.domain.objects.DefaultStoreOfRelations
|
||||
|
@ -346,6 +347,9 @@ open class EditorPresentationTestSetup {
|
|||
lateinit var fileLimitsEventChannel: FileLimitsEventChannel
|
||||
lateinit var interceptFileLimitEvents: InterceptFileLimitEvents
|
||||
|
||||
@Mock
|
||||
lateinit var setObjectInternalFlags: SetObjectInternalFlags
|
||||
|
||||
open fun buildViewModel(urlBuilder: UrlBuilder = builder): EditorViewModel {
|
||||
|
||||
val storage = Editor.Storage()
|
||||
|
@ -467,7 +471,8 @@ open class EditorPresentationTestSetup {
|
|||
workspaceManager = workspaceManager,
|
||||
getObjectTypes = getObjectTypes,
|
||||
interceptFileLimitEvents = interceptFileLimitEvents,
|
||||
addRelationToObject = addRelationToObject
|
||||
addRelationToObject = addRelationToObject,
|
||||
setObjectInternalFlags = setObjectInternalFlags
|
||||
)
|
||||
}
|
||||
|
||||
|
@ -746,4 +751,16 @@ open class EditorPresentationTestSetup {
|
|||
} doReturn Resultat.success(types)
|
||||
}
|
||||
}
|
||||
|
||||
fun stubFileLimitEvents() {
|
||||
interceptFileLimitEvents.stub {
|
||||
onBlocking { run(Unit) } doReturn emptyFlow()
|
||||
}
|
||||
}
|
||||
|
||||
fun stubSetInternalFlags() {
|
||||
setObjectInternalFlags.stub {
|
||||
onBlocking { async(any()) } doReturn Resultat.success(Payload(root, emptyList()))
|
||||
}
|
||||
}
|
||||
}
|
|
@ -257,8 +257,7 @@ message Rpc {
|
|||
}
|
||||
string storePath = 3; // Path to local storage
|
||||
int64 icon = 4; // Option of pre-installed icon
|
||||
|
||||
string alphaInviteCode = 20; // DEPRECATED
|
||||
bool disableLocalNetworkSync = 5; // Disable local network discovery
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -363,6 +362,7 @@ message Rpc {
|
|||
option (no_auth) = true;
|
||||
string id = 1; // Id of a selected account
|
||||
string rootPath = 2; // Root path is optional, set if this is a first request
|
||||
bool disableLocalNetworkSync = 3; // Disable local network discovery
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -548,6 +548,27 @@ message Rpc {
|
|||
}
|
||||
}
|
||||
}
|
||||
|
||||
message EnableLocalNetworkSync {
|
||||
message Request {
|
||||
}
|
||||
message Response {
|
||||
Error error = 2;
|
||||
|
||||
message Error {
|
||||
Code code = 1;
|
||||
string description = 2;
|
||||
|
||||
enum Code {
|
||||
NULL = 0;
|
||||
UNKNOWN_ERROR = 1;
|
||||
BAD_INPUT = 2;
|
||||
ACCOUNT_IS_NOT_RUNNING = 4;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
message Workspace {
|
||||
|
@ -1498,6 +1519,7 @@ message Rpc {
|
|||
}
|
||||
}
|
||||
}
|
||||
|
||||
message SetInternalFlags {
|
||||
message Request {
|
||||
string contextId = 1;
|
||||
|
@ -1739,6 +1761,28 @@ message Rpc {
|
|||
}
|
||||
}
|
||||
|
||||
message ListSetObjectType {
|
||||
message Request {
|
||||
repeated string objectIds = 1;
|
||||
string objectTypeId = 2;
|
||||
}
|
||||
message Response {
|
||||
Error error = 1;
|
||||
|
||||
message Error {
|
||||
Code code = 1;
|
||||
string description = 2;
|
||||
|
||||
enum Code {
|
||||
NULL = 0;
|
||||
UNKNOWN_ERROR = 1;
|
||||
BAD_INPUT = 2;
|
||||
UNKNOWN_OBJECT_TYPE_URL = 3;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
message ApplyTemplate {
|
||||
message Request {
|
||||
string contextId = 1;
|
||||
|
@ -5364,6 +5408,26 @@ message Rpc {
|
|||
}
|
||||
}
|
||||
|
||||
message OpenedObjects {
|
||||
message Request {}
|
||||
|
||||
message Response {
|
||||
Error error = 1;
|
||||
repeated string objectIDs = 2;
|
||||
|
||||
message Error {
|
||||
Code code = 1;
|
||||
string description = 2;
|
||||
|
||||
enum Code {
|
||||
NULL = 0;
|
||||
UNKNOWN_ERROR = 1;
|
||||
BAD_INPUT = 2;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
message Ping {
|
||||
message Request {
|
||||
int32 index = 1;
|
||||
|
|
|
@ -581,6 +581,7 @@ message Account {
|
|||
string localStoragePath = 103; // path to local storage
|
||||
string timeZone = 104; // time zone from config
|
||||
string analyticsId = 105;
|
||||
string networkId = 106; // network id to which anytype is connected
|
||||
}
|
||||
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue
Block a user