mirror of
https://github.com/anyproto/anytype-kotlin.git
synced 2025-06-11 10:18:05 +09:00
DROID-944 Library | Enhancement | Implemented installing and uninstalling types and relations (#2898)
DROID-944 Library | Enhancement | Implemented installing and uninstalling types and relations
This commit is contained in:
parent
9c70819e1a
commit
b3f6835056
26 changed files with 398 additions and 81 deletions
|
@ -9,4 +9,9 @@ sealed class LibraryEvent {
|
|||
class LibraryRelations(override val query: String) : Query(query)
|
||||
}
|
||||
|
||||
sealed class ToggleInstall(open val item: LibraryView) : LibraryEvent() {
|
||||
class Type(override val item: LibraryView) : ToggleInstall(item)
|
||||
class Relation(override val item: LibraryView) : ToggleInstall(item)
|
||||
}
|
||||
|
||||
}
|
|
@ -1,7 +1,6 @@
|
|||
package com.anytypeio.anytype.presentation.library
|
||||
|
||||
import com.anytypeio.anytype.core_models.ObjectWrapper
|
||||
import com.anytypeio.anytype.presentation.navigation.LibraryView
|
||||
import kotlinx.coroutines.FlowPreview
|
||||
import kotlinx.coroutines.flow.Flow
|
||||
import kotlinx.coroutines.flow.MutableStateFlow
|
||||
|
|
|
@ -0,0 +1,41 @@
|
|||
package com.anytypeio.anytype.presentation.library
|
||||
|
||||
import android.content.Context
|
||||
import android.content.res.Resources
|
||||
import com.anytypeio.anytype.presentation.R
|
||||
import javax.inject.Inject
|
||||
|
||||
interface LibraryResourceManager {
|
||||
|
||||
fun messageRelationAdded(name: String): String
|
||||
fun messageRelationRemoved(name: String): String
|
||||
fun messageTypeAdded(name: String): String
|
||||
fun messageTypeRemoved(name: String): String
|
||||
|
||||
val errorMessage: String
|
||||
|
||||
class Impl @Inject constructor(
|
||||
val context: Context
|
||||
) : LibraryResourceManager {
|
||||
|
||||
private val resources: Resources = context.resources
|
||||
|
||||
override fun messageRelationAdded(name: String) =
|
||||
resources.getString(R.string.library_relation_added, name)
|
||||
|
||||
override fun messageRelationRemoved(name: String) =
|
||||
resources.getString(R.string.library_relation_removed, name)
|
||||
|
||||
override fun messageTypeAdded(name: String) =
|
||||
resources.getString(R.string.library_type_added, name)
|
||||
|
||||
|
||||
override fun messageTypeRemoved(name: String) =
|
||||
resources.getString(R.string.library_type_removed, name)
|
||||
|
||||
override val errorMessage: String =
|
||||
resources.getString(R.string.library_something_went_wrong)
|
||||
|
||||
}
|
||||
|
||||
}
|
|
@ -1,6 +1,5 @@
|
|||
package com.anytypeio.anytype.presentation.library
|
||||
|
||||
import com.anytypeio.anytype.presentation.navigation.LibraryView
|
||||
|
||||
class LibraryScreenState(
|
||||
val types: Tabs.Types,
|
||||
|
|
|
@ -0,0 +1,67 @@
|
|||
package com.anytypeio.anytype.presentation.library
|
||||
|
||||
import com.anytypeio.anytype.core_models.Id
|
||||
import com.anytypeio.anytype.core_models.RelationFormat
|
||||
import com.anytypeio.anytype.presentation.objects.ObjectIcon
|
||||
|
||||
sealed interface DependentData {
|
||||
|
||||
class Model(
|
||||
val item: LibraryView,
|
||||
) : DependentData
|
||||
|
||||
object None : DependentData
|
||||
|
||||
}
|
||||
|
||||
sealed interface LibraryView {
|
||||
val id: Id
|
||||
val name: String
|
||||
val dependentData: DependentData
|
||||
|
||||
class MyTypeView(
|
||||
override val id: Id,
|
||||
override val name: String,
|
||||
val icon: ObjectIcon? = null,
|
||||
val sourceObject: Id? = null,
|
||||
val readOnly: Boolean = false,
|
||||
override val dependentData: DependentData = DependentData.None
|
||||
) : LibraryView
|
||||
|
||||
data class LibraryTypeView(
|
||||
override val id: Id,
|
||||
override val name: String,
|
||||
val icon: ObjectIcon? = null,
|
||||
val objectTypeId: Id? = null,
|
||||
override val dependentData: DependentData = DependentData.None
|
||||
) : LibraryView
|
||||
|
||||
class MyRelationView(
|
||||
override val id: Id,
|
||||
override val name: String,
|
||||
val format: RelationFormat,
|
||||
val sourceObject: Id? = null,
|
||||
val readOnly: Boolean = false,
|
||||
override val dependentData: DependentData = DependentData.None
|
||||
) : LibraryView
|
||||
|
||||
data class LibraryRelationView(
|
||||
override val id: Id,
|
||||
override val name: String,
|
||||
val format: RelationFormat,
|
||||
override val dependentData: DependentData = DependentData.None
|
||||
) : LibraryView
|
||||
|
||||
class UnknownView(
|
||||
override val id: Id = "",
|
||||
override val name: String = "",
|
||||
override val dependentData: DependentData = DependentData.None
|
||||
) : LibraryView
|
||||
|
||||
class CreateNewTypeView(
|
||||
override val id: Id = "",
|
||||
override val name: String = "",
|
||||
override val dependentData: DependentData = DependentData.None
|
||||
) : LibraryView
|
||||
|
||||
}
|
|
@ -3,11 +3,15 @@ package com.anytypeio.anytype.presentation.library
|
|||
import androidx.lifecycle.ViewModel
|
||||
import androidx.lifecycle.ViewModelProvider
|
||||
import androidx.lifecycle.viewModelScope
|
||||
import com.anytypeio.anytype.core_models.Id
|
||||
import com.anytypeio.anytype.domain.base.fold
|
||||
import com.anytypeio.anytype.domain.workspace.AddObjectToWorkspace
|
||||
import com.anytypeio.anytype.domain.workspace.RemoveObjectsFromWorkspace
|
||||
import com.anytypeio.anytype.presentation.common.BaseViewModel
|
||||
import com.anytypeio.anytype.presentation.library.delegates.LibraryRelationsDelegate
|
||||
import com.anytypeio.anytype.presentation.library.delegates.LibraryTypesDelegate
|
||||
import com.anytypeio.anytype.presentation.library.delegates.MyRelationsDelegate
|
||||
import com.anytypeio.anytype.presentation.library.delegates.MyTypesDelegate
|
||||
import com.anytypeio.anytype.presentation.navigation.LibraryView
|
||||
import javax.inject.Inject
|
||||
import kotlinx.coroutines.flow.MutableStateFlow
|
||||
import kotlinx.coroutines.flow.SharingStarted
|
||||
|
@ -15,13 +19,17 @@ import kotlinx.coroutines.flow.StateFlow
|
|||
import kotlinx.coroutines.flow.combine
|
||||
import kotlinx.coroutines.flow.stateIn
|
||||
import kotlinx.coroutines.launch
|
||||
import timber.log.Timber
|
||||
|
||||
class LibraryViewModel(
|
||||
private val myTypesDelegate: MyTypesDelegate,
|
||||
private val libraryTypesDelegate: LibraryTypesDelegate,
|
||||
private val myRelationsDelegate: MyRelationsDelegate,
|
||||
private val libraryRelationsDelegate: LibraryRelationsDelegate
|
||||
) : ViewModel() {
|
||||
private val libraryRelationsDelegate: LibraryRelationsDelegate,
|
||||
private val addObjectToWorkspace: AddObjectToWorkspace,
|
||||
private val removeObjectsFromWorkspace: RemoveObjectsFromWorkspace,
|
||||
private val resourceManager: LibraryResourceManager
|
||||
) : BaseViewModel() {
|
||||
|
||||
private val uiEvents = MutableStateFlow<LibraryEvent>(LibraryEvent.Query.MyTypes(""))
|
||||
|
||||
|
@ -41,11 +49,75 @@ class LibraryViewModel(
|
|||
is LibraryEvent.Query.LibraryRelations -> {
|
||||
libraryRelationsDelegate.onQueryLibRelations(it.query)
|
||||
}
|
||||
is LibraryEvent.ToggleInstall -> {
|
||||
proceedWithToggleInstall(it.item)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private fun proceedWithToggleInstall(item: LibraryView) {
|
||||
when (val dependentData = item.dependentData) {
|
||||
is DependentData.Model -> {
|
||||
proceedWithUnInstallingObject(item, dependentData.item.id)
|
||||
}
|
||||
is DependentData.None -> {
|
||||
proceedWithInstallingObject(item)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private fun proceedWithInstallingObject(item: LibraryView) {
|
||||
viewModelScope.launch {
|
||||
addObjectToWorkspace(AddObjectToWorkspace.Params(listOf(item.id))).proceed(
|
||||
success = {
|
||||
when (item) {
|
||||
is LibraryView.LibraryRelationView -> {
|
||||
sendToast(resourceManager.messageRelationAdded(item.name))
|
||||
}
|
||||
is LibraryView.LibraryTypeView -> {
|
||||
sendToast(resourceManager.messageTypeAdded(item.name))
|
||||
}
|
||||
else -> {
|
||||
Timber.e("Unsupported item type: $item")
|
||||
}
|
||||
}
|
||||
},
|
||||
failure = {
|
||||
Timber.e(it, "Error while adding relation to workspace.")
|
||||
sendToast(resourceManager.errorMessage)
|
||||
}
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
private fun proceedWithUnInstallingObject(item: LibraryView, id: Id) {
|
||||
viewModelScope.launch {
|
||||
removeObjectsFromWorkspace.execute(
|
||||
RemoveObjectsFromWorkspace.Params(listOf(id))
|
||||
).fold(
|
||||
onFailure = {
|
||||
Timber.e(it, "Error while removing relation from workspace.")
|
||||
sendToast(resourceManager.errorMessage)
|
||||
},
|
||||
onSuccess = {
|
||||
when (item) {
|
||||
is LibraryView.LibraryRelationView -> {
|
||||
sendToast(resourceManager.messageRelationRemoved(item.name))
|
||||
}
|
||||
is LibraryView.LibraryTypeView -> {
|
||||
sendToast(resourceManager.messageTypeRemoved(item.name))
|
||||
}
|
||||
else -> {
|
||||
Timber.e("Unsupported item type: $item")
|
||||
}
|
||||
}
|
||||
}
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
fun eventStream(event: LibraryEvent) {
|
||||
uiEvents.value = event
|
||||
}
|
||||
|
@ -93,9 +165,17 @@ class LibraryViewModel(
|
|||
return libTypes.copy(
|
||||
items = libTypes.items.map { libType ->
|
||||
if (libType is LibraryView.LibraryTypeView) {
|
||||
libType.copy(installed = myTypes.items.find { myType ->
|
||||
(myType as? LibraryView.MyTypeView)?.sourceObject == libType.id
|
||||
} != null)
|
||||
with(
|
||||
myTypes.items.find {
|
||||
(it as? LibraryView.MyTypeView)?.sourceObject == libType.id
|
||||
}
|
||||
) {
|
||||
libType.copy(
|
||||
dependentData = if (this != null) {
|
||||
DependentData.Model(item = this)
|
||||
} else DependentData.None
|
||||
)
|
||||
}
|
||||
} else {
|
||||
libType
|
||||
}
|
||||
|
@ -110,9 +190,17 @@ class LibraryViewModel(
|
|||
return libRelations.copy(
|
||||
items = libRelations.items.map { libRelation ->
|
||||
if (libRelation is LibraryView.LibraryRelationView) {
|
||||
libRelation.copy(installed = myRelations.items.find { myType ->
|
||||
(myType as LibraryView.MyRelationView).sourceObject == libRelation.id
|
||||
} != null)
|
||||
with(
|
||||
myRelations.items.find {
|
||||
(it as? LibraryView.MyRelationView)?.sourceObject == libRelation.id
|
||||
}
|
||||
) {
|
||||
libRelation.copy(
|
||||
dependentData = if (this != null) {
|
||||
DependentData.Model(item = this)
|
||||
} else DependentData.None
|
||||
)
|
||||
}
|
||||
} else {
|
||||
libRelation
|
||||
}
|
||||
|
@ -124,7 +212,10 @@ class LibraryViewModel(
|
|||
private val myTypesDelegate: MyTypesDelegate,
|
||||
private val libraryTypesDelegate: LibraryTypesDelegate,
|
||||
private val myRelationsDelegate: MyRelationsDelegate,
|
||||
private val libraryRelationsDelegate: LibraryRelationsDelegate
|
||||
private val libraryRelationsDelegate: LibraryRelationsDelegate,
|
||||
private val addObjectToWorkspace: AddObjectToWorkspace,
|
||||
private val removeObjectsFromWorkspace: RemoveObjectsFromWorkspace,
|
||||
private val resourceManager: LibraryResourceManager
|
||||
) : ViewModelProvider.Factory {
|
||||
@Suppress("UNCHECKED_CAST")
|
||||
override fun <T : ViewModel> create(modelClass: Class<T>): T {
|
||||
|
@ -132,7 +223,10 @@ class LibraryViewModel(
|
|||
myTypesDelegate,
|
||||
libraryTypesDelegate,
|
||||
myRelationsDelegate,
|
||||
libraryRelationsDelegate
|
||||
libraryRelationsDelegate,
|
||||
addObjectToWorkspace,
|
||||
removeObjectsFromWorkspace,
|
||||
resourceManager
|
||||
) as T
|
||||
}
|
||||
}
|
||||
|
|
|
@ -12,9 +12,9 @@ import com.anytypeio.anytype.domain.workspace.WorkspaceManager
|
|||
import com.anytypeio.anytype.presentation.dashboard.DEFAULT_KEYS
|
||||
import com.anytypeio.anytype.presentation.library.LibraryListDelegate
|
||||
import com.anytypeio.anytype.presentation.library.LibraryScreenState
|
||||
import com.anytypeio.anytype.presentation.library.LibraryView
|
||||
import com.anytypeio.anytype.presentation.library.QueryListenerMyTypes
|
||||
import com.anytypeio.anytype.presentation.library.filterByQuery
|
||||
import com.anytypeio.anytype.presentation.navigation.LibraryView
|
||||
import com.anytypeio.anytype.presentation.objects.toLibraryViews
|
||||
import com.anytypeio.anytype.presentation.search.ObjectSearchConstants
|
||||
import javax.inject.Inject
|
||||
|
|
|
@ -29,50 +29,3 @@ fun ObjectView.isContainsText(text: String): Boolean = title.contains(text, true
|
|||
|
||||
fun List<ObjectView>.filterBy(text: String): List<ObjectView> =
|
||||
if (text.isNotEmpty()) this.filter { it.isContainsText(text) } else this
|
||||
|
||||
|
||||
sealed interface LibraryView {
|
||||
val id: Id
|
||||
val name: String
|
||||
|
||||
class MyTypeView(
|
||||
override val id: Id,
|
||||
override val name: String,
|
||||
val icon: ObjectIcon? = null,
|
||||
val sourceObject: Id? = null,
|
||||
val readOnly: Boolean = false
|
||||
) : LibraryView
|
||||
|
||||
data class LibraryTypeView(
|
||||
override val id: Id,
|
||||
override val name: String,
|
||||
val icon: ObjectIcon? = null,
|
||||
val installed: Boolean = false,
|
||||
) : LibraryView
|
||||
|
||||
class MyRelationView(
|
||||
override val id: Id,
|
||||
override val name: String,
|
||||
val format: RelationFormat,
|
||||
val sourceObject: Id? = null,
|
||||
val readOnly: Boolean = false
|
||||
) : LibraryView
|
||||
|
||||
data class LibraryRelationView(
|
||||
override val id: Id,
|
||||
override val name: String,
|
||||
val format: RelationFormat,
|
||||
val installed: Boolean = false,
|
||||
) : LibraryView
|
||||
|
||||
class UnknownView(
|
||||
override val id: Id = "",
|
||||
override val name: String = "",
|
||||
) : LibraryView
|
||||
|
||||
class CreateNewTypeView(
|
||||
override val id: Id = "",
|
||||
override val name: String = ""
|
||||
) : LibraryView
|
||||
|
||||
}
|
|
@ -9,7 +9,7 @@ import com.anytypeio.anytype.core_models.Relations.SOURCE_OBJECT
|
|||
import com.anytypeio.anytype.domain.misc.UrlBuilder
|
||||
import com.anytypeio.anytype.presentation.linking.LinkToItemView
|
||||
import com.anytypeio.anytype.presentation.navigation.DefaultObjectView
|
||||
import com.anytypeio.anytype.presentation.navigation.LibraryView
|
||||
import com.anytypeio.anytype.presentation.library.LibraryView
|
||||
import com.anytypeio.anytype.presentation.relations.RelationValueView
|
||||
import com.anytypeio.anytype.presentation.sets.filter.CreateFilterView
|
||||
import timber.log.Timber
|
||||
|
@ -72,7 +72,6 @@ fun List<ObjectWrapper.Basic>.toLibraryViews(
|
|||
layout = obj.getProperLayout(),
|
||||
builder = urlBuilder
|
||||
),
|
||||
installed = false,
|
||||
)
|
||||
}
|
||||
ObjectTypeIds.OBJECT_TYPE -> {
|
||||
|
|
|
@ -1,3 +1,10 @@
|
|||
<resources>
|
||||
<string name="app_name">presentation</string>
|
||||
|
||||
<string name="library_type_added">Type `%1$s` added to your library"</string>
|
||||
<string name="library_type_removed">Type `%1$s` removed from your library"</string>
|
||||
<string name="library_relation_added">Relation `%1$s` added to your library"</string>
|
||||
<string name="library_relation_removed">Relation `%1$s` removed from your library"</string>
|
||||
<string name="library_something_went_wrong">Something went wrong. Please, try again later.</string>
|
||||
|
||||
</resources>
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue