Objects | Feature | Delete relations from object (#1741)

* added delete actions

* fixed tests

* added request for deleting relation from object

* fixes

* fixes

* added restrictions

* run ci

* ci off, fixes
This commit is contained in:
Evgenii Kozlov 2021-08-20 14:41:54 +03:00 committed by GitHub
parent 9b42bc3719
commit 1f4fe5829d
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
25 changed files with 376 additions and 33 deletions

View File

@ -7,6 +7,7 @@ import com.anytypeio.anytype.domain.block.repo.BlockRepository
import com.anytypeio.anytype.domain.dataview.interactor.ObjectRelationList
import com.anytypeio.anytype.domain.misc.UrlBuilder
import com.anytypeio.anytype.domain.relations.AddToFeaturedRelations
import com.anytypeio.anytype.domain.relations.DeleteRelationFromObject
import com.anytypeio.anytype.domain.relations.RemoveFromFeaturedRelations
import com.anytypeio.anytype.presentation.editor.Editor
import com.anytypeio.anytype.presentation.editor.editor.DetailModificationManager
@ -43,7 +44,8 @@ object DocumentRelationModule {
updateDetail: UpdateDetail,
detailModificationManager: DetailModificationManager,
addToFeaturedRelations: AddToFeaturedRelations,
removeFromFeaturedRelations: RemoveFromFeaturedRelations
removeFromFeaturedRelations: RemoveFromFeaturedRelations,
deleteRelationFromObject: DeleteRelationFromObject
): ObjectRelationListViewModelFactory {
return ObjectRelationListViewModelFactory(
stores = stores,
@ -53,7 +55,8 @@ object DocumentRelationModule {
updateDetail = updateDetail,
detailModificationManager = detailModificationManager,
addToFeaturedRelations = addToFeaturedRelations,
removeFromFeaturedRelations = removeFromFeaturedRelations
removeFromFeaturedRelations = removeFromFeaturedRelations,
deleteRelationFromObject = deleteRelationFromObject
)
}
@ -73,4 +76,9 @@ object DocumentRelationModule {
@Provides
@PerModal
fun removeFromFeaturedRelations(repo: BlockRepository) : RemoveFromFeaturedRelations = RemoveFromFeaturedRelations(repo)
@JvmStatic
@Provides
@PerModal
fun deleteRelationFromObject(repo: BlockRepository) : DeleteRelationFromObject = DeleteRelationFromObject(repo)
}

View File

@ -58,6 +58,12 @@ open class RelationListFragment : BaseBottomSheetFragment(),
ctx = ctx,
view = it.view
)
},
onDeleteClicked = {
vm.onDeleteClicked(
ctx = ctx,
view = it.view
)
}
)
}
@ -92,7 +98,7 @@ open class RelationListFragment : BaseBottomSheetFragment(),
RelationAddToObjectFragment.new(ctx).show(childFragmentManager, null)
}
btnEditOrDone.setOnClickListener {
toast(getString(R.string.coming_soon))
vm.onEditOrDoneClicked()
}
}
@ -126,6 +132,15 @@ open class RelationListFragment : BaseBottomSheetFragment(),
}
subscribe(vm.commands) { command -> execute(command) }
subscribe(vm.toasts) { toast(it) }
subscribe(vm.isEditMode) { isEditMode ->
if (isEditMode) {
btnEditOrDone.setText(R.string.done)
btnPlus.invisible()
} else {
btnPlus.visible()
btnEditOrDone.setText(R.string.edit)
}
}
}
}

View File

@ -4,16 +4,40 @@ package com.anytypeio.anytype.core_models
* Keys for predefined, bundled relations.
*/
object Relations {
const val ID = "id"
const val COVER_TYPE = "coverType"
const val DESCRIPTION = "description"
const val LAYOUT = "layout"
const val NAME = "name"
const val ICON_EMOJI = "iconEmoji"
const val ICON_IMAGE = "iconImage"
const val RELATION_FORMAT = "relationFormat"
const val IS_ARCHIVED = "isArchived"
const val IS_READ_ONLY = "isReadonly"
const val IS_HIDDEN = "isHidden"
const val LAST_OPENED_DATE = "lastOpenedDate"
const val TYPE = "type"
const val DONE = "done"
const val FEATURED_RELATIONS = "featuredRelations"
const val FILE_EXT = "fileExt"
const val FILE_MIME_TYPE = "fileMimeType"
const val NUMBER_DEFAULT_VALUE = "0"
val defaultRelations = listOf(
ID,
NAME,
DESCRIPTION,
ICON_EMOJI,
ICON_IMAGE,
RELATION_FORMAT,
TYPE,
LAYOUT,
IS_HIDDEN,
IS_ARCHIVED,
IS_READ_ONLY,
DONE,
FILE_EXT,
FILE_MIME_TYPE
)
}

View File

@ -32,6 +32,12 @@ sealed class RelationViewHolder(view: View) : BlockViewHolder(view), BlockViewHo
}
}
fun setIsRemovable(isRemoveable: Boolean) {
itemView.findViewById<View>(R.id.actionsLeftContainer).apply {
if (isRemoveable) visible() else gone()
}
}
fun setBackgroundColor(color: String? = null) {
Timber.d("Setting background color: $color")
if (color != null) {

View File

@ -8,7 +8,6 @@ import androidx.recyclerview.widget.RecyclerView
import com.anytypeio.anytype.core_ui.R
import com.anytypeio.anytype.core_ui.features.editor.holders.relations.RelationViewHolder
import com.anytypeio.anytype.core_ui.features.editor.slash.holders.RelationsSubheaderMenuHolder
import com.anytypeio.anytype.core_ui.features.relations.DocumentRelationAdapter
import com.anytypeio.anytype.core_utils.diff.DefaultDiffUtil
import com.anytypeio.anytype.core_utils.ext.gone
import com.anytypeio.anytype.core_utils.ext.visible
@ -117,15 +116,6 @@ class SlashRelationsAdapter(
}
}
}
R.layout.item_relation_list_section -> {
DocumentRelationAdapter.SectionViewHolder(
view = inflater.inflate(
viewType,
parent,
false
)
)
}
R.layout.item_slash_widget_subheader -> {
RelationsSubheaderMenuHolder(
view = inflater.inflate(viewType, parent, false)

View File

@ -16,7 +16,8 @@ import com.anytypeio.anytype.core_ui.features.editor.holders.relations.RelationV
class DocumentRelationAdapter(
private var items: List<RelationListViewModel.Model>,
private val onRelationClicked: (RelationListViewModel.Model.Item) -> Unit,
private val onCheckboxClicked: (RelationListViewModel.Model.Item) -> Unit
private val onCheckboxClicked: (RelationListViewModel.Model.Item) -> Unit,
private val onDeleteClicked: (RelationListViewModel.Model.Item) -> Unit
) : RecyclerView.Adapter<RecyclerView.ViewHolder>() {
override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): RecyclerView.ViewHolder {
@ -34,6 +35,14 @@ class DocumentRelationAdapter(
check(view is RelationListViewModel.Model.Item)
onCheckboxClicked(view)
}
itemView.findViewById<View>(R.id.ivActionDelete).setOnClickListener {
val pos = bindingAdapterPosition
if (pos != RecyclerView.NO_POSITION) {
val view = items[bindingAdapterPosition]
check(view is RelationListViewModel.Model.Item)
onDeleteClicked(view)
}
}
}
}
R.layout.item_relation_list_relation_checkbox -> {
@ -48,6 +57,14 @@ class DocumentRelationAdapter(
check(view is RelationListViewModel.Model.Item)
onCheckboxClicked(view)
}
itemView.findViewById<View>(R.id.ivActionDelete).setOnClickListener {
val pos = bindingAdapterPosition
if (pos != RecyclerView.NO_POSITION) {
val view = items[bindingAdapterPosition]
check(view is RelationListViewModel.Model.Item)
onDeleteClicked(view)
}
}
}
}
R.layout.item_relation_list_relation_object -> {
@ -62,6 +79,14 @@ class DocumentRelationAdapter(
check(view is RelationListViewModel.Model.Item)
onCheckboxClicked(view)
}
itemView.findViewById<View>(R.id.ivActionDelete).setOnClickListener {
val pos = bindingAdapterPosition
if (pos != RecyclerView.NO_POSITION) {
val view = items[bindingAdapterPosition]
check(view is RelationListViewModel.Model.Item)
onDeleteClicked(view)
}
}
}
}
R.layout.item_relation_list_relation_status -> {
@ -76,6 +101,14 @@ class DocumentRelationAdapter(
check(view is RelationListViewModel.Model.Item)
onCheckboxClicked(view)
}
itemView.findViewById<View>(R.id.ivActionDelete).setOnClickListener {
val pos = bindingAdapterPosition
if (pos != RecyclerView.NO_POSITION) {
val view = items[bindingAdapterPosition]
check(view is RelationListViewModel.Model.Item)
onDeleteClicked(view)
}
}
}
}
R.layout.item_relation_list_relation_tag -> {
@ -90,6 +123,14 @@ class DocumentRelationAdapter(
check(view is RelationListViewModel.Model.Item)
onCheckboxClicked(view)
}
itemView.findViewById<View>(R.id.ivActionDelete).setOnClickListener {
val pos = bindingAdapterPosition
if (pos != RecyclerView.NO_POSITION) {
val view = items[bindingAdapterPosition]
check(view is RelationListViewModel.Model.Item)
onDeleteClicked(view)
}
}
}
}
R.layout.item_relation_list_relation_file -> {
@ -104,6 +145,14 @@ class DocumentRelationAdapter(
check(view is RelationListViewModel.Model.Item)
onCheckboxClicked(view)
}
itemView.findViewById<View>(R.id.ivActionDelete).setOnClickListener {
val pos = bindingAdapterPosition
if (pos != RecyclerView.NO_POSITION) {
val view = items[bindingAdapterPosition]
check(view is RelationListViewModel.Model.Item)
onDeleteClicked(view)
}
}
}
}
R.layout.item_relation_list_section -> {
@ -113,6 +162,32 @@ class DocumentRelationAdapter(
}
}
override fun onBindViewHolder(
holder: RecyclerView.ViewHolder,
position: Int,
payloads: MutableList<Any>
) {
if (payloads.isEmpty()) {
super.onBindViewHolder(holder, position, payloads)
} else {
if (holder is ViewHolder) {
payloads.forEach { payload ->
if (payload is GranularChange) {
if (payload.isModeChanged) {
val item = items[position]
check(item is RelationListViewModel.Model.Item)
holder.setIsRemovable(item.isRemoveable)
} else {
super.onBindViewHolder(holder, position, payloads)
}
}
}
} else {
super.onBindViewHolder(holder, position, payloads)
}
}
}
override fun onBindViewHolder(holder: RecyclerView.ViewHolder, position: Int) {
val item = items[position]
when (holder) {
@ -156,11 +231,14 @@ class DocumentRelationAdapter(
check(item is RelationListViewModel.Model.Section)
holder.bind(item)
}
else -> { Timber.d("Skipping binding for: $holder") }
else -> {
Timber.d("Skipping binding for: $holder")
}
}
if (holder is ViewHolder) {
check(item is RelationListViewModel.Model.Item)
holder.setIsFeatured(item.view.isFeatured)
holder.setIsRemovable(item.isRemoveable)
}
}
@ -168,7 +246,7 @@ class DocumentRelationAdapter(
override fun getItemViewType(position: Int): Int = when (val item = items[position]) {
is RelationListViewModel.Model.Item -> {
when(item.view) {
when (item.view) {
is DocumentRelationView.Checkbox -> R.layout.item_relation_list_relation_checkbox
is DocumentRelationView.Object -> R.layout.item_relation_list_relation_object
is DocumentRelationView.Status -> R.layout.item_relation_list_relation_status
@ -184,7 +262,7 @@ class DocumentRelationAdapter(
fun update(update: List<RelationListViewModel.Model>) {
Timber.d("Updating adapter: $update")
val differ = DefaultDiffUtil(old = items, new = update)
val differ = Differ(old = items, new = update)
val result = DiffUtil.calculateDiff(differ, false)
items = update
result.dispatchUpdatesTo(this)
@ -192,7 +270,7 @@ class DocumentRelationAdapter(
class SectionViewHolder(view: View) : RecyclerView.ViewHolder(view) {
fun bind(section: RelationListViewModel.Model.Section) {
when(section) {
when (section) {
RelationListViewModel.Model.Section.Featured -> {
itemView.tvSectionName.setText(R.string.featured_relations)
}
@ -203,4 +281,23 @@ class DocumentRelationAdapter(
}
}
}
class Differ(
private val old: List<RelationListViewModel.Model>,
private val new: List<RelationListViewModel.Model>
) : DefaultDiffUtil<RelationListViewModel.Model>(old = old, new = new) {
override fun getChangePayload(oldItemPosition: Int, newItemPosition: Int): Any? {
val oldItem = old[oldItemPosition]
val newItem = new[newItemPosition]
return if (oldItem is RelationListViewModel.Model.Item && newItem is RelationListViewModel.Model.Item) {
if (newItem.isRemoveable != oldItem.isRemoveable)
GranularChange(isModeChanged = true)
else
null
} else
null
}
}
data class GranularChange(val isModeChanged: Boolean = false)
}

View File

@ -9,6 +9,20 @@
android:layout_height="wrap_content"
android:orientation="horizontal">
<FrameLayout
android:id="@+id/actionsLeftContainer"
android:layout_width="24dp"
android:layout_height="24dp"
android:layout_gravity="center_vertical"
android:layout_marginEnd="8dp"
android:visibility="gone">
<ImageView
android:id="@+id/ivActionDelete"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:src="@drawable/ic_relation_delete" />
</FrameLayout>
<include
layout="@layout/item_document_relation_checkbox"
android:layout_width="0dp"

View File

@ -1,14 +1,28 @@
<?xml version="1.0" encoding="utf-8"?>
<FrameLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:background="@drawable/default_ripple"
android:layout_width="match_parent"
android:layout_height="wrap_content">
android:layout_height="wrap_content"
android:background="@drawable/default_ripple">
<LinearLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:orientation="horizontal">
<FrameLayout
android:id="@+id/actionsLeftContainer"
android:layout_width="24dp"
android:layout_height="24dp"
android:layout_gravity="center_vertical"
android:layout_marginEnd="8dp"
android:visibility="gone">
<ImageView
android:id="@+id/ivActionDelete"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:src="@drawable/ic_relation_delete" />
</FrameLayout>
<include
layout="@layout/item_document_relation_default"
android:layout_width="0dp"
@ -27,9 +41,9 @@
<include
android:id="@+id/divider"
layout="@layout/view_divider"
android:layout_width="match_parent"
android:layout_height="0.5dp"
layout="@layout/view_divider"
android:layout_gravity="bottom"
android:visibility="gone" />

View File

@ -1,14 +1,28 @@
<?xml version="1.0" encoding="utf-8"?>
<FrameLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:background="@drawable/default_ripple"
android:layout_width="match_parent"
android:layout_height="wrap_content">
android:layout_height="wrap_content"
android:background="@drawable/default_ripple">
<LinearLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:orientation="horizontal">
<FrameLayout
android:id="@+id/actionsLeftContainer"
android:layout_width="24dp"
android:layout_height="24dp"
android:layout_gravity="center_vertical"
android:layout_marginEnd="8dp"
android:visibility="gone">
<ImageView
android:id="@+id/ivActionDelete"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:src="@drawable/ic_relation_delete" />
</FrameLayout>
<include
layout="@layout/item_document_relation_file"
android:layout_width="0dp"
@ -27,9 +41,9 @@
<include
android:id="@+id/divider"
layout="@layout/view_divider"
android:layout_width="match_parent"
android:layout_height="0.5dp"
layout="@layout/view_divider"
android:layout_gravity="bottom"
android:visibility="gone" />

View File

@ -9,6 +9,20 @@
android:layout_height="wrap_content"
android:orientation="horizontal">
<FrameLayout
android:id="@+id/actionsLeftContainer"
android:layout_width="24dp"
android:layout_height="24dp"
android:layout_gravity="center_vertical"
android:layout_marginEnd="8dp"
android:visibility="gone">
<ImageView
android:id="@+id/ivActionDelete"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:src="@drawable/ic_relation_delete" />
</FrameLayout>
<include
layout="@layout/item_document_relation_object"
android:layout_width="0dp"

View File

@ -9,6 +9,20 @@
android:layout_height="wrap_content"
android:orientation="horizontal">
<FrameLayout
android:id="@+id/actionsLeftContainer"
android:layout_width="24dp"
android:layout_height="24dp"
android:layout_gravity="center_vertical"
android:layout_marginEnd="8dp"
android:visibility="gone">
<ImageView
android:id="@+id/ivActionDelete"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:src="@drawable/ic_relation_delete" />
</FrameLayout>
<include
layout="@layout/item_document_relation_status"
android:layout_width="0dp"

View File

@ -9,6 +9,20 @@
android:layout_height="wrap_content"
android:orientation="horizontal">
<FrameLayout
android:id="@+id/actionsLeftContainer"
android:layout_width="24dp"
android:layout_height="24dp"
android:layout_gravity="center_vertical"
android:layout_marginEnd="8dp"
android:visibility="gone">
<ImageView
android:id="@+id/ivActionDelete"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:src="@drawable/ic_relation_delete" />
</FrameLayout>
<include
layout="@layout/item_document_relation_tag"
android:layout_width="0dp"

View File

@ -7,7 +7,7 @@ import androidx.recyclerview.widget.DiffUtil
* [T] should also implement [DefaultObjectDiffIdentifier]. Otherwise, [areItemsTheSame] won't work.
* @see [DefaultObjectDiffIdentifier]
*/
class DefaultDiffUtil<in T : DefaultObjectDiffIdentifier>(
open class DefaultDiffUtil<in T : DefaultObjectDiffIdentifier>(
private val old: List<T>,
private val new: List<T>
) : DiffUtil.Callback() {

View File

@ -427,6 +427,10 @@ class BlockDataRepository(
ctx: Id, relation: Id
): Payload = factory.remote.addRelationToObject(ctx, relation)
override suspend fun deleteRelationFromObject(ctx: Id, relation: Id): Payload {
return factory.remote.deleteRelationFromObject(ctx = ctx, relation = relation)
}
override suspend fun addNewRelationToObject(
ctx: Id,
name: String,

View File

@ -154,6 +154,7 @@ interface BlockDataStore {
suspend fun relationListAvailable(ctx: Id): List<Relation>
suspend fun addRelationToObject(ctx: Id, relation: Id) : Payload
suspend fun deleteRelationFromObject(ctx: Id, relation: Id): Payload
suspend fun addNewRelationToObject(ctx: Id, name: String, format: RelationFormat) : Payload
suspend fun debugSync(): String

View File

@ -160,6 +160,7 @@ interface BlockRemote {
suspend fun relationListAvailable(ctx: Id): List<Relation>
suspend fun addRelationToObject(ctx: Id, relation: Id) : Payload
suspend fun deleteRelationFromObject(ctx: Id, relation: Id): Payload
suspend fun addNewRelationToObject(ctx: Id, name: String, format: RelationFormat) : Payload
suspend fun debugSync(): String

View File

@ -348,7 +348,7 @@ class BlockRemoteDataStore(private val remote: BlockRemote) : BlockDataStore {
override suspend fun addRelationToObject(
ctx: Id,
relation: Id
): Payload = remote.addRelationToObject(ctx, relation)
): Payload = remote.addRelationToObject(ctx = ctx, relation = relation)
override suspend fun addNewRelationToObject(
ctx: Id,
@ -360,6 +360,11 @@ class BlockRemoteDataStore(private val remote: BlockRemote) : BlockDataStore {
name = name
)
override suspend fun deleteRelationFromObject(
ctx: Id,
relation: Id
): Payload = remote.deleteRelationFromObject(ctx = ctx, relation = relation)
override suspend fun debugSync(): String = remote.debugSync()
override suspend fun turnInto(

View File

@ -209,6 +209,7 @@ interface BlockRepository {
suspend fun relationListAvailable(ctx: Id): List<Relation>
suspend fun addRelationToObject(ctx: Id, relation: Id): Payload
suspend fun deleteRelationFromObject(ctx: Id, relation: Id): Payload
suspend fun addNewRelationToObject(ctx: Id, name: String, format: RelationFormat): Payload
suspend fun debugSync(): String

View File

@ -0,0 +1,30 @@
package com.anytypeio.anytype.domain.relations
import com.anytypeio.anytype.core_models.Id
import com.anytypeio.anytype.core_models.Payload
import com.anytypeio.anytype.domain.base.BaseUseCase
import com.anytypeio.anytype.domain.block.repo.BlockRepository
/**
* Use-case for deleting a relation from an object.
*/
class DeleteRelationFromObject(
private val repo: BlockRepository
) : BaseUseCase<Payload, DeleteRelationFromObject.Params>() {
override suspend fun run(params: Params) = safe {
repo.deleteRelationFromObject(
ctx = params.ctx,
relation = params.relation
)
}
/**
* @param ctx id of the object
* @param relation relation id or key
*/
class Params(
val ctx: Id,
val relation: Id
)
}

View File

@ -379,6 +379,14 @@ class BlockMiddleware(
name = name
)
override suspend fun deleteRelationFromObject(
ctx: Id,
relation: Id
): Payload = middleware.deleteRelationFromObject(
ctx = ctx,
relation = relation
)
override suspend fun debugSync(): String = middleware.debugSync()
override suspend fun turnInto(

View File

@ -1416,6 +1416,17 @@ class Middleware(
return response.event.toPayload()
}
fun deleteRelationFromObject(ctx: Id, relation: Id) : Payload {
val request = Rpc.Object.RelationDelete.Request(
contextId = ctx,
relationKey = relation
)
if (BuildConfig.DEBUG) logRequest(request)
val response = service.objectRelationDelete(request)
if (BuildConfig.DEBUG) logResponse(response)
return response.event.toPayload()
}
fun addToFeaturedRelations(
ctx: Id,
relations: List<Id>

View File

@ -168,6 +168,9 @@ interface MiddlewareService {
@Throws(Exception::class)
fun objectRelationAdd(request: Object.RelationAdd.Request) : Object.RelationAdd.Response
@Throws(Exception::class)
fun objectRelationDelete(request: Object.RelationDelete.Request) : Object.RelationDelete.Response
@Throws(Exception::class)
fun debugSync(request: Debug.Sync.Request) : Debug.Sync.Response

View File

@ -656,6 +656,19 @@ class MiddlewareServiceImplementation : MiddlewareService {
}
}
override fun objectRelationDelete(request: Object.RelationDelete.Request): Object.RelationDelete.Response {
val encoded = Service.objectRelationDelete(
Object.RelationDelete.Request.ADAPTER.encode(request)
)
val response = Object.RelationDelete.Response.ADAPTER.decode(encoded)
val error = response.error
if (error != null && error.code != Object.RelationDelete.Response.Error.Code.NULL) {
throw Exception(error.description)
} else {
return response
}
}
override fun blockAddRelation(request: Block.Relation.Add.Request): Block.Relation.Add.Response {
val encoded = Service.blockRelationAdd(
Block.Relation.Add.Request.ADAPTER.encode(request)

View File

@ -7,6 +7,7 @@ import com.anytypeio.anytype.domain.`object`.UpdateDetail
import com.anytypeio.anytype.domain.dataview.interactor.ObjectRelationList
import com.anytypeio.anytype.domain.misc.UrlBuilder
import com.anytypeio.anytype.domain.relations.AddToFeaturedRelations
import com.anytypeio.anytype.domain.relations.DeleteRelationFromObject
import com.anytypeio.anytype.domain.relations.RemoveFromFeaturedRelations
import com.anytypeio.anytype.presentation.editor.Editor
import com.anytypeio.anytype.presentation.editor.editor.DetailModificationManager
@ -20,7 +21,8 @@ class ObjectRelationListViewModelFactory(
private val updateDetail: UpdateDetail,
private val detailModificationManager: DetailModificationManager,
private val addToFeaturedRelations: AddToFeaturedRelations,
private val removeFromFeaturedRelations: RemoveFromFeaturedRelations
private val removeFromFeaturedRelations: RemoveFromFeaturedRelations,
private val deleteRelationFromObject: DeleteRelationFromObject
) : ViewModelProvider.Factory {
@Suppress("UNCHECKED_CAST")
@ -33,7 +35,8 @@ class ObjectRelationListViewModelFactory(
updateDetail = updateDetail,
detailModificationManager = detailModificationManager,
addToFeaturedRelations = addToFeaturedRelations,
removeFromFeaturedRelations = removeFromFeaturedRelations
removeFromFeaturedRelations = removeFromFeaturedRelations,
deleteRelationFromObject = deleteRelationFromObject
) as T
}
}

View File

@ -4,11 +4,13 @@ import androidx.lifecycle.viewModelScope
import com.anytypeio.anytype.core_models.Id
import com.anytypeio.anytype.core_models.Payload
import com.anytypeio.anytype.core_models.Relation
import com.anytypeio.anytype.core_models.Relations
import com.anytypeio.anytype.core_utils.diff.DefaultObjectDiffIdentifier
import com.anytypeio.anytype.domain.`object`.UpdateDetail
import com.anytypeio.anytype.domain.dataview.interactor.ObjectRelationList
import com.anytypeio.anytype.domain.misc.UrlBuilder
import com.anytypeio.anytype.domain.relations.AddToFeaturedRelations
import com.anytypeio.anytype.domain.relations.DeleteRelationFromObject
import com.anytypeio.anytype.domain.relations.RemoveFromFeaturedRelations
import com.anytypeio.anytype.presentation.common.BaseViewModel
import com.anytypeio.anytype.presentation.editor.Editor
@ -27,9 +29,12 @@ class RelationListViewModel(
private val updateDetail: UpdateDetail,
private val detailModificationManager: DetailModificationManager,
private val addToFeaturedRelations: AddToFeaturedRelations,
private val removeFromFeaturedRelations: RemoveFromFeaturedRelations
private val removeFromFeaturedRelations: RemoveFromFeaturedRelations,
private val deleteRelationFromObject: DeleteRelationFromObject
) : BaseViewModel() {
val isEditMode = MutableStateFlow(false)
private val jobs = mutableListOf<Job>()
private val isInAddMode = MutableStateFlow(false)
@ -43,7 +48,12 @@ class RelationListViewModel(
val detail = details.details[ctx]
val values = detail?.map ?: emptyMap()
val featured = detail?.featuredRelations ?: emptyList()
relations.views(details, values, urlBuilder, featured).map { Model.Item(it) }
relations.views(details, values, urlBuilder, featured).map { view ->
Model.Item(
view = view,
isRemoveable = isEditMode.value && !Relations.defaultRelations.contains(view.relationId)
)
}
}.map { views ->
val result = mutableListOf<Model>().apply {
val (isFeatured, other) = views.partition { it.view.isFeatured }
@ -111,6 +121,33 @@ class RelationListViewModel(
}
}
fun onDeleteClicked(ctx: Id, view: DocumentRelationView) {
viewModelScope.launch {
deleteRelationFromObject(
DeleteRelationFromObject.Params(
ctx = ctx,
relation = view.relationId
)
).process(
failure = { Timber.e(it, "Error while deleting relation") },
success = { dispatcher.send(it) }
)
}
}
fun onEditOrDoneClicked() {
isEditMode.value = !isEditMode.value
views.value = views.value.map { view ->
if (view is Model.Item) {
view.copy(
isRemoveable = isEditMode.value && !Relations.defaultRelations.contains(view.view.relationId)
)
} else {
view
}
}
}
private fun onRelationClickedAddMode(
target: Id?,
view: DocumentRelationView
@ -237,12 +274,16 @@ class RelationListViewModel(
object Featured : Section() {
override val identifier: String get() = "Section_Featured"
}
object Other : Section() {
override val identifier: String get() = "Section_Other"
}
}
data class Item(val view: DocumentRelationView) : Model() {
data class Item(
val view: DocumentRelationView,
val isRemoveable: Boolean = false
) : Model() {
override val identifier: String get() = view.identifier
}
}
@ -273,8 +314,6 @@ class RelationListViewModel(
}
companion object {
const val MAX_FEATURED_RELATION_COUNT = 5
const val MAX_FEATURED_RELATION_COUNT_ERROR = "Currently you cannot create more than $MAX_FEATURED_RELATION_COUNT featured relations"
const val NOT_ALLOWED_FOR_RELATION = "Not allowed for this relation"
}
}