mirror of
https://github.com/anyproto/anytype-kotlin.git
synced 2025-06-08 05:47:05 +09:00
Data View | Enable pagination (#1561)
This commit is contained in:
parent
5ddf5b43ee
commit
79d4b261d4
14 changed files with 230 additions and 80 deletions
|
@ -18,6 +18,7 @@
|
|||
* Navigate to objects from data view or relation-value screens (#1539)
|
||||
* Show the Android keyboard reliably for text-based relations with empty value (#1542)
|
||||
* Do not exit edit mode when deleting one of the values from relation's file list (#1543)
|
||||
* Data view pagination (#1561)
|
||||
|
||||
## Version 0.1.11
|
||||
|
||||
|
|
|
@ -131,8 +131,12 @@ open class ObjectSetFragment :
|
|||
subscribe(bottomPanel.touches()) { swipeDetector.onTouchEvent(it) }
|
||||
}
|
||||
|
||||
paginatorToolbar.onNumberClickCallback = { (num, isSelected) ->
|
||||
vm.onPaginatorToolbarNumberClicked(num, isSelected)
|
||||
with(paginatorToolbar) {
|
||||
onNumberClickCallback = { (num, isSelected) ->
|
||||
vm.onPaginatorToolbarNumberClicked(num, isSelected)
|
||||
}
|
||||
onNext = { vm.onPaginatorNextElsePrevious(true) }
|
||||
onPrevious = { vm.onPaginatorNextElsePrevious(false) }
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -371,6 +375,15 @@ open class ObjectSetFragment :
|
|||
jobs += lifecycleScope.subscribe(vm.commands) { observeCommands(it) }
|
||||
jobs += lifecycleScope.subscribe(vm.header.filterNotNull()) { observeHeader(it) }
|
||||
jobs += lifecycleScope.subscribe(vm.viewerGrid) { observeGrid(it) }
|
||||
jobs += lifecycleScope.subscribe(vm.pagination) { (index, count) ->
|
||||
paginatorToolbar.set(count = count, index = index)
|
||||
if (count > 1) {
|
||||
paginatorToolbar.visible()
|
||||
}
|
||||
else {
|
||||
paginatorToolbar.gone()
|
||||
}
|
||||
}
|
||||
jobs += lifecycleScope.subscribe(vm.isLoading) { isLoading ->
|
||||
Timber.d("isLoading: $isLoading")
|
||||
if (isLoading) {
|
||||
|
|
|
@ -158,7 +158,6 @@
|
|||
app:layout_constraintTop_toBottomOf="parent" />
|
||||
|
||||
<com.anytypeio.anytype.core_ui.widgets.toolbar.DataViewPaginatorToolbar
|
||||
android:visibility="invisible"
|
||||
android:id="@+id/paginatorToolbar"
|
||||
app:layout_constraintEnd_toEndOf="parent"
|
||||
app:layout_constraintStart_toStartOf="parent"
|
||||
|
|
|
@ -70,17 +70,25 @@
|
|||
motion:layout_constraintTop_toTopOf="@+id/addNewButton" />
|
||||
<Constraint
|
||||
android:id="@id/dvProgressBar"
|
||||
motion:visibilityMode="ignore"
|
||||
motion:layout_constraintBottom_toBottomOf="@+id/gridContainer"
|
||||
motion:layout_constraintEnd_toEndOf="parent"
|
||||
motion:layout_constraintStart_toStartOf="parent"
|
||||
motion:layout_constraintBottom_toBottomOf="@+id/gridContainer" />
|
||||
motion:visibilityMode="ignore" />
|
||||
<Constraint
|
||||
android:id="@id/logoProgressBar"
|
||||
motion:visibilityMode="ignore"
|
||||
motion:layout_constraintBottom_toBottomOf="@+id/objectSetIcon"
|
||||
motion:layout_constraintEnd_toEndOf="@+id/objectSetIcon"
|
||||
motion:layout_constraintStart_toStartOf="@+id/objectSetIcon"
|
||||
motion:layout_constraintTop_toTopOf="@+id/objectSetIcon" />
|
||||
motion:layout_constraintTop_toTopOf="@+id/objectSetIcon"
|
||||
motion:visibilityMode="ignore" />
|
||||
<Constraint
|
||||
android:id="@id/paginatorToolbar"
|
||||
android:layout_width="0dp"
|
||||
android:layout_height="@dimen/default_toolbar_height"
|
||||
motion:layout_constraintBottom_toBottomOf="parent"
|
||||
motion:layout_constraintEnd_toEndOf="parent"
|
||||
motion:layout_constraintStart_toStartOf="parent"
|
||||
motion:visibilityMode="ignore" />
|
||||
</ConstraintSet>
|
||||
|
||||
<ConstraintSet android:id="@+id/end">
|
||||
|
@ -146,16 +154,24 @@
|
|||
motion:layout_constraintTop_toBottomOf="@+id/tvCurrentViewerName" />
|
||||
<Constraint
|
||||
android:id="@id/dvProgressBar"
|
||||
motion:visibilityMode="ignore"
|
||||
motion:layout_constraintBottom_toBottomOf="@+id/gridContainer"
|
||||
motion:layout_constraintEnd_toEndOf="parent"
|
||||
motion:layout_constraintStart_toStartOf="parent"
|
||||
motion:layout_constraintBottom_toBottomOf="@+id/gridContainer" />
|
||||
motion:visibilityMode="ignore" />
|
||||
<Constraint
|
||||
android:id="@id/logoProgressBar"
|
||||
motion:visibilityMode="ignore"
|
||||
motion:layout_constraintBottom_toBottomOf="@+id/objectSetIcon"
|
||||
motion:layout_constraintEnd_toEndOf="@+id/objectSetIcon"
|
||||
motion:layout_constraintStart_toStartOf="@+id/objectSetIcon"
|
||||
motion:layout_constraintTop_toTopOf="@+id/objectSetIcon" />
|
||||
motion:layout_constraintTop_toTopOf="@+id/objectSetIcon"
|
||||
motion:visibilityMode="ignore" />
|
||||
<Constraint
|
||||
android:id="@id/paginatorToolbar"
|
||||
android:layout_width="0dp"
|
||||
android:layout_height="@dimen/default_toolbar_height"
|
||||
motion:layout_constraintBottom_toBottomOf="parent"
|
||||
motion:layout_constraintEnd_toEndOf="parent"
|
||||
motion:layout_constraintStart_toStartOf="parent"
|
||||
motion:visibilityMode="ignore" />
|
||||
</ConstraintSet>
|
||||
</MotionScene>
|
|
@ -20,7 +20,9 @@ class DataViewPaginatorToolbar @JvmOverloads constructor(
|
|||
attrs: AttributeSet? = null
|
||||
) : FrameLayout(context, attrs) {
|
||||
|
||||
var onNumberClickCallback : (Pair<Int, Boolean>) -> Unit = {}
|
||||
var onNumberClickCallback: (Pair<Int, Boolean>) -> Unit = {}
|
||||
var onNext: () -> Unit = {}
|
||||
var onPrevious: () -> Unit = {}
|
||||
|
||||
private val paginatorAdapter = Adapter { onNumberClickCallback(it) }
|
||||
|
||||
|
@ -29,31 +31,50 @@ class DataViewPaginatorToolbar @JvmOverloads constructor(
|
|||
setBackgroundColor(Color.WHITE)
|
||||
rvPaginator.apply {
|
||||
layoutManager = LinearLayoutManager(context, LinearLayoutManager.HORIZONTAL, false)
|
||||
val spacing = resources.getDimension(R.dimen.dp_12).toInt()
|
||||
addItemDecoration(
|
||||
SpacingItemDecoration(
|
||||
spacingStart = resources.getDimension(R.dimen.dp_12).toInt(),
|
||||
spacingEnd = resources.getDimension(R.dimen.dp_12).toInt()
|
||||
spacingStart = spacing,
|
||||
spacingEnd = spacing,
|
||||
firstItemSpacingStart = spacing * 2,
|
||||
lastItemSpacingEnd = spacing * 2
|
||||
)
|
||||
)
|
||||
adapter = paginatorAdapter
|
||||
}
|
||||
ivNextPage.setOnClickListener { onNext() }
|
||||
ivPreviousPage.setOnClickListener { onPrevious() }
|
||||
}
|
||||
|
||||
fun set(count: Int, index: Int) {
|
||||
val update = mutableListOf<Pair<Int, Boolean>>()
|
||||
repeat(count) {
|
||||
val number = it.inc()
|
||||
val number = it
|
||||
update.add(
|
||||
Pair(number, index == number)
|
||||
)
|
||||
}
|
||||
paginatorAdapter.submitList(update)
|
||||
if (index > 0) rvPaginator.smoothScrollToPosition(index)
|
||||
if (index == 0) {
|
||||
ivPreviousPage.isEnabled = false
|
||||
ivPreviousPage.alpha = 0.2f
|
||||
} else {
|
||||
ivPreviousPage.isEnabled = true
|
||||
ivPreviousPage.alpha = 1.0f
|
||||
}
|
||||
if (index == count - 1) {
|
||||
ivNextPage.isEnabled = false
|
||||
ivNextPage.alpha = 0.2f
|
||||
} else {
|
||||
ivNextPage.isEnabled = true
|
||||
ivNextPage.alpha = 1f
|
||||
}
|
||||
}
|
||||
|
||||
class Adapter(
|
||||
private val onNumberClicked: (Pair<Int, Boolean>) -> Unit
|
||||
): ListAdapter<Pair<Int, Boolean>, Adapter.ViewHolder>(PageNumberDiffer) {
|
||||
) : ListAdapter<Pair<Int, Boolean>, Adapter.ViewHolder>(PageNumberDiffer) {
|
||||
|
||||
override fun onCreateViewHolder(
|
||||
parent: ViewGroup, viewType: Int
|
||||
|
@ -79,7 +100,7 @@ class DataViewPaginatorToolbar @JvmOverloads constructor(
|
|||
) {
|
||||
fun bind(item: Pair<Int, Boolean>) {
|
||||
val (num, isSelected) = item
|
||||
itemView.tvNumber.text = num.toString()
|
||||
itemView.tvNumber.text = num.inc().toString()
|
||||
itemView.tvNumber.isSelected = isSelected
|
||||
}
|
||||
}
|
||||
|
@ -90,6 +111,7 @@ class DataViewPaginatorToolbar @JvmOverloads constructor(
|
|||
oldItem: Pair<Int, Boolean>,
|
||||
newItem: Pair<Int, Boolean>
|
||||
): Boolean = newItem.first == oldItem.first
|
||||
|
||||
override fun areContentsTheSame(
|
||||
oldItem: Pair<Int, Boolean>,
|
||||
newItem: Pair<Int, Boolean>
|
||||
|
|
|
@ -1,30 +1,30 @@
|
|||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<merge xmlns:android="http://schemas.android.com/apk/res/android">
|
||||
|
||||
<ImageView
|
||||
<ImageView
|
||||
android:id="@+id/ivPreviousPage"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_gravity="center_vertical"
|
||||
android:layout_marginStart="12dp"
|
||||
android:src="@drawable/ic_paginator_arrow"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"/>
|
||||
|
||||
android:src="@drawable/ic_paginator_arrow" />
|
||||
|
||||
<androidx.recyclerview.widget.RecyclerView
|
||||
android:overScrollMode="never"
|
||||
android:scrollbars="none"
|
||||
android:id="@+id/rvPaginator"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="match_parent"
|
||||
android:layout_marginStart="36dp"
|
||||
android:layout_marginEnd="36dp"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="match_parent"/>
|
||||
android:overScrollMode="never"
|
||||
android:scrollbars="none" />
|
||||
|
||||
<ImageView
|
||||
android:rotation="180"
|
||||
android:id="@+id/ivNextPage"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_gravity="center_vertical|end"
|
||||
android:layout_marginEnd="12dp"
|
||||
android:src="@drawable/ic_paginator_arrow"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"/>
|
||||
android:rotation="180"
|
||||
android:src="@drawable/ic_paginator_arrow" />
|
||||
|
||||
</merge>
|
|
@ -15,7 +15,6 @@ org.gradle.caching=true
|
|||
org.gradle.jvmargs=-Xmx3072m -XX:MaxPermSize=512m -XX:+HeapDumpOnOutOfMemoryError -Dfile.encoding=UTF-8
|
||||
org.gradle.configureondemand=true
|
||||
|
||||
android.enableR8=true
|
||||
android.useAndroidX=true
|
||||
android.enableJetifier=false
|
||||
|
||||
|
|
|
@ -37,6 +37,8 @@ object ObjectSetConfig {
|
|||
const val FILE_EXT_KEY = "fileExt"
|
||||
|
||||
const val FILE_MIME_KEY = "fileMimeType"
|
||||
|
||||
const val DEFAULT_LIMIT = 50
|
||||
}
|
||||
|
||||
val Map<String, Any?>.type: String
|
||||
|
|
|
@ -1,10 +1,8 @@
|
|||
package com.anytypeio.anytype.presentation.sets
|
||||
|
||||
import com.anytypeio.anytype.core_models.DV
|
||||
import com.anytypeio.anytype.core_models.DVViewer
|
||||
import com.anytypeio.anytype.core_models.Event
|
||||
import com.anytypeio.anytype.core_models.Event.Command
|
||||
import com.anytypeio.anytype.core_models.Id
|
||||
import com.anytypeio.anytype.presentation.extension.updateFields
|
||||
import kotlinx.coroutines.channels.Channel
|
||||
import kotlinx.coroutines.flow.*
|
||||
|
@ -13,15 +11,9 @@ import timber.log.Timber
|
|||
class ObjectSetReducer {
|
||||
|
||||
private val eventChannel: Channel<List<Event>> = Channel()
|
||||
private val effectChannel: Channel<List<SideEffect>> = Channel()
|
||||
|
||||
val state = MutableStateFlow(ObjectSet.init())
|
||||
|
||||
val effects = effectChannel
|
||||
.consumeAsFlow()
|
||||
.filter { it.isNotEmpty() }
|
||||
.flatMapConcat { it.asFlow() }
|
||||
.distinctUntilChanged()
|
||||
val effects = MutableSharedFlow<List<SideEffect>>()
|
||||
|
||||
suspend fun run() {
|
||||
eventChannel
|
||||
|
@ -34,7 +26,7 @@ class ObjectSetReducer {
|
|||
}
|
||||
.collect { transformation ->
|
||||
state.value = transformation.state
|
||||
effectChannel.send(transformation.effects)
|
||||
effects.emit(transformation.effects)
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -67,6 +59,7 @@ class ObjectSetReducer {
|
|||
)
|
||||
}
|
||||
is Command.DataView.SetView -> {
|
||||
effects.add(SideEffect.ResetOffset(event.offset))
|
||||
state.copy(
|
||||
blocks = state.blocks.map { block ->
|
||||
if (block.id == event.target) {
|
||||
|
@ -179,14 +172,10 @@ class ObjectSetReducer {
|
|||
}
|
||||
|
||||
sealed class SideEffect {
|
||||
data class ViewerUpdate(
|
||||
val target: Id,
|
||||
val viewer: DVViewer
|
||||
) : SideEffect()
|
||||
data class ResetOffset(val offset: Int) : SideEffect()
|
||||
}
|
||||
|
||||
fun clear() {
|
||||
eventChannel.close()
|
||||
effectChannel.close()
|
||||
}
|
||||
}
|
|
@ -4,6 +4,7 @@ import androidx.lifecycle.MutableLiveData
|
|||
import androidx.lifecycle.ViewModel
|
||||
import androidx.lifecycle.viewModelScope
|
||||
import com.anytypeio.anytype.core_models.*
|
||||
import com.anytypeio.anytype.core_models.ext.content
|
||||
import com.anytypeio.anytype.core_models.restrictions.DataViewRestriction
|
||||
import com.anytypeio.anytype.core_utils.common.EventWrapper
|
||||
import com.anytypeio.anytype.domain.block.interactor.UpdateText
|
||||
|
@ -28,6 +29,7 @@ import kotlinx.coroutines.channels.Channel
|
|||
import kotlinx.coroutines.flow.*
|
||||
import kotlinx.coroutines.launch
|
||||
import timber.log.Timber
|
||||
import kotlin.math.ceil
|
||||
|
||||
class ObjectSetViewModel(
|
||||
private val reducer: ObjectSetReducer,
|
||||
|
@ -46,6 +48,16 @@ class ObjectSetViewModel(
|
|||
private val session: ObjectSetSession
|
||||
) : ViewModel(), SupportNavigation<EventWrapper<AppNavigation.Command>> {
|
||||
|
||||
|
||||
private val total = MutableStateFlow(0)
|
||||
private val offset = MutableStateFlow(0)
|
||||
|
||||
val pagination = total.combine(offset) { t, o ->
|
||||
val idx = ceil(o.toDouble() / ObjectSetConfig.DEFAULT_LIMIT).toInt()
|
||||
val pages = ceil(t.toDouble() / ObjectSetConfig.DEFAULT_LIMIT).toInt()
|
||||
Pair(idx, pages)
|
||||
}
|
||||
|
||||
private val _viewerTabs = MutableStateFlow<List<ViewerTabView>>(emptyList())
|
||||
val viewerTabs = _viewerTabs.asStateFlow()
|
||||
|
||||
|
@ -84,29 +96,29 @@ class ObjectSetViewModel(
|
|||
reducer.state.filter { it.isInitialized }.collect { set ->
|
||||
Timber.d("Set updated!")
|
||||
_viewerTabs.value = set.tabs(session.currentViewerId)
|
||||
val viewerIndex =
|
||||
reducer.state.value.viewers.indexOfFirst { it.id == session.currentViewerId }
|
||||
val viewerIndex = set.viewers.indexOfFirst { it.id == session.currentViewerId }
|
||||
set.render(viewerIndex, context, urlBuilder).let { vs ->
|
||||
_viewerGrid.value = vs.viewer
|
||||
_header.value = vs.title
|
||||
}
|
||||
if (set.viewers.isNotEmpty()) {
|
||||
val viewer = if (viewerIndex != -1)
|
||||
set.viewers[viewerIndex]
|
||||
else
|
||||
set.viewers.first()
|
||||
val db = set.viewerDb[viewer.id]
|
||||
total.value = db?.total ?: 0
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
viewModelScope.launch {
|
||||
reducer.effects.collect { effect ->
|
||||
when (effect) {
|
||||
is ObjectSetReducer.SideEffect.ViewerUpdate -> {
|
||||
updateDataViewViewer(
|
||||
UpdateDataViewViewer.Params(
|
||||
context = context,
|
||||
target = effect.target,
|
||||
viewer = effect.viewer
|
||||
)
|
||||
).process(
|
||||
success = defaultPayloadConsumer,
|
||||
failure = { Timber.e(it, "Error while updating data view's viewer") }
|
||||
)
|
||||
reducer.effects.collect { effects ->
|
||||
effects.forEach { effect ->
|
||||
when (effect) {
|
||||
is ObjectSetReducer.SideEffect.ResetOffset -> {
|
||||
offset.value = effect.offset
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -144,7 +156,10 @@ class ObjectSetViewModel(
|
|||
viewModelScope.launch {
|
||||
isLoading.value = true
|
||||
openObjectSet(ctx).process(
|
||||
success = { defaultPayloadConsumer(it).also { isLoading.value = false } },
|
||||
success = { payload ->
|
||||
defaultPayloadConsumer(payload).also { isLoading.value = false }
|
||||
proceedWithStartupPaging()
|
||||
},
|
||||
failure = {
|
||||
isLoading.value = false
|
||||
Timber.e(it, "Error while opening object set: $ctx")
|
||||
|
@ -191,7 +206,7 @@ class ObjectSetViewModel(
|
|||
context = context,
|
||||
block = reducer.state.value.dataview.id,
|
||||
view = viewer,
|
||||
limit = 0,
|
||||
limit = ObjectSetConfig.DEFAULT_LIMIT,
|
||||
offset = 0
|
||||
)
|
||||
).process(
|
||||
|
@ -569,16 +584,61 @@ class ObjectSetViewModel(
|
|||
return dVRestrictions != null && dVRestrictions.restrictions.any { it == restriction }
|
||||
}
|
||||
|
||||
//region {PAGINATION LOGIC}
|
||||
//region { PAGINATION LOGIC }
|
||||
|
||||
private suspend fun proceedWithStartupPaging() {
|
||||
val set = reducer.state.value.dataview
|
||||
val dv = set.content<Block.Content.DataView>()
|
||||
val viewer = dv.viewers.find { it.id == session.currentViewerId } ?: dv.viewers.first()
|
||||
proceedWithViewerPaging(set = set, viewer = viewer.id)
|
||||
}
|
||||
|
||||
fun onPaginatorToolbarNumberClicked(number: Int, isSelected: Boolean) {
|
||||
if (isSelected) {
|
||||
Timber.d("This page is already selected")
|
||||
} else {
|
||||
// TODO proceed with pagination logic.
|
||||
viewModelScope.launch {
|
||||
offset.value = number * ObjectSetConfig.DEFAULT_LIMIT
|
||||
val set = reducer.state.value.dataview
|
||||
val dv = set.content<Block.Content.DataView>()
|
||||
val viewer = dv.viewers.find { it.id == session.currentViewerId } ?: dv.viewers.first()
|
||||
proceedWithViewerPaging(set = set, viewer = viewer.id)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
fun onPaginatorNextElsePrevious(next: Boolean) {
|
||||
viewModelScope.launch {
|
||||
offset.value = if (next) {
|
||||
offset.value + ObjectSetConfig.DEFAULT_LIMIT
|
||||
} else {
|
||||
offset.value - ObjectSetConfig.DEFAULT_LIMIT
|
||||
}
|
||||
val set = reducer.state.value.dataview
|
||||
val dv = set.content<Block.Content.DataView>()
|
||||
val viewer = dv.viewers.find { it.id == session.currentViewerId } ?: dv.viewers.first()
|
||||
proceedWithViewerPaging(set = set, viewer = viewer.id)
|
||||
}
|
||||
}
|
||||
|
||||
private suspend fun proceedWithViewerPaging(
|
||||
set: Block,
|
||||
viewer: Id
|
||||
) {
|
||||
setActiveViewer(
|
||||
SetActiveViewer.Params(
|
||||
context = context,
|
||||
block = set.id,
|
||||
view = viewer,
|
||||
limit = ObjectSetConfig.DEFAULT_LIMIT,
|
||||
offset = offset.value
|
||||
)
|
||||
).process(
|
||||
success = { payload -> defaultPayloadConsumer(payload) },
|
||||
failure = { Timber.e(it, "Error while setting view during pagination") }
|
||||
)
|
||||
}
|
||||
|
||||
//endregion
|
||||
|
||||
override fun onCleared() {
|
||||
|
|
|
@ -2,8 +2,8 @@ package com.anytypeio.anytype.presentation.sets
|
|||
|
||||
import MockDataFactory
|
||||
import com.anytypeio.anytype.core_models.Block
|
||||
import com.anytypeio.anytype.core_models.Relation
|
||||
import com.anytypeio.anytype.core_models.Event
|
||||
import com.anytypeio.anytype.core_models.Relation
|
||||
import org.junit.Before
|
||||
import org.junit.Test
|
||||
import kotlin.test.assertEquals
|
||||
|
@ -202,8 +202,10 @@ class ObjectSetReducerTest {
|
|||
children = listOf()
|
||||
)
|
||||
|
||||
val expected =
|
||||
ObjectSetReducer.Transformation(ObjectSet(blocks = listOf(title, expectedDataView)))
|
||||
val expected = ObjectSetReducer.Transformation(
|
||||
state = ObjectSet(blocks = listOf(title, expectedDataView)),
|
||||
effects = listOf(ObjectSetReducer.SideEffect.ResetOffset(event.offset))
|
||||
)
|
||||
|
||||
assertEquals(expected, result)
|
||||
}
|
||||
|
@ -356,8 +358,10 @@ class ObjectSetReducerTest {
|
|||
children = listOf()
|
||||
)
|
||||
|
||||
val expected =
|
||||
ObjectSetReducer.Transformation(ObjectSet(blocks = listOf(title, expectedDataView)))
|
||||
val expected = ObjectSetReducer.Transformation(
|
||||
state = ObjectSet(blocks = listOf(title, expectedDataView)),
|
||||
effects = listOf(ObjectSetReducer.SideEffect.ResetOffset(event.offset))
|
||||
)
|
||||
|
||||
assertEquals(expected, result)
|
||||
}
|
||||
|
|
|
@ -3,7 +3,11 @@ package com.anytypeio.anytype.presentation.sets.main
|
|||
import MockDataFactory
|
||||
import androidx.arch.core.executor.testing.InstantTaskExecutorRule
|
||||
import com.anytypeio.anytype.core_models.Event
|
||||
import com.anytypeio.anytype.core_models.Payload
|
||||
import com.anytypeio.anytype.domain.base.Either
|
||||
import com.anytypeio.anytype.domain.dataview.interactor.SetActiveViewer
|
||||
import com.anytypeio.anytype.presentation.TypicalTwoRecordObjectSet
|
||||
import com.anytypeio.anytype.presentation.relations.ObjectSetConfig
|
||||
import com.anytypeio.anytype.presentation.sets.model.CellView
|
||||
import com.anytypeio.anytype.presentation.sets.model.ColumnView
|
||||
import com.anytypeio.anytype.presentation.sets.model.Viewer
|
||||
|
@ -12,6 +16,8 @@ import org.junit.Before
|
|||
import org.junit.Rule
|
||||
import org.junit.Test
|
||||
import org.mockito.MockitoAnnotations
|
||||
import org.mockito.kotlin.doReturn
|
||||
import org.mockito.kotlin.stub
|
||||
import kotlin.test.assertEquals
|
||||
import kotlin.test.assertTrue
|
||||
|
||||
|
@ -54,17 +60,54 @@ class ObjectSetSettingActiveViewerTest : ObjectSetViewModelTestSetup() {
|
|||
)
|
||||
)
|
||||
)
|
||||
stubSetActiveViewer(
|
||||
events = listOf(
|
||||
Event.Command.DataView.SetRecords(
|
||||
|
||||
setActiveViewer.stub {
|
||||
onBlocking { invoke(
|
||||
SetActiveViewer.Params(
|
||||
context = root,
|
||||
id = doc.dv.id,
|
||||
view = doc.viewer2.id,
|
||||
records = updatedRecords,
|
||||
total = MockDataFactory.randomInt()
|
||||
block = doc.dv.id,
|
||||
view = doc.viewer1.id,
|
||||
limit = ObjectSetConfig.DEFAULT_LIMIT
|
||||
)
|
||||
) } doReturn Either.Right(
|
||||
Payload(
|
||||
context = root,
|
||||
events = listOf(
|
||||
Event.Command.DataView.SetRecords(
|
||||
context = root,
|
||||
view = doc.viewer1.id,
|
||||
id = doc.dv.id,
|
||||
total = MockDataFactory.randomInt(),
|
||||
records = doc.initialRecords
|
||||
)
|
||||
)
|
||||
)
|
||||
)
|
||||
)
|
||||
}
|
||||
|
||||
setActiveViewer.stub {
|
||||
onBlocking { invoke(
|
||||
SetActiveViewer.Params(
|
||||
context = root,
|
||||
block = doc.dv.id,
|
||||
view = doc.viewer2.id,
|
||||
limit = ObjectSetConfig.DEFAULT_LIMIT
|
||||
)
|
||||
) } doReturn Either.Right(
|
||||
Payload(
|
||||
context = root,
|
||||
events = listOf(
|
||||
Event.Command.DataView.SetRecords(
|
||||
context = root,
|
||||
id = doc.dv.id,
|
||||
view = doc.viewer2.id,
|
||||
records = updatedRecords,
|
||||
total = MockDataFactory.randomInt()
|
||||
)
|
||||
)
|
||||
)
|
||||
)
|
||||
}
|
||||
|
||||
val vm = buildViewModel()
|
||||
|
||||
|
|
|
@ -8,6 +8,7 @@ import com.anytypeio.anytype.core_models.Event
|
|||
import com.anytypeio.anytype.domain.dataview.interactor.SetActiveViewer
|
||||
import com.anytypeio.anytype.domain.dataview.interactor.UpdateDataViewViewer
|
||||
import com.anytypeio.anytype.presentation.TypicalTwoRecordObjectSet
|
||||
import com.anytypeio.anytype.presentation.relations.ObjectSetConfig
|
||||
import com.anytypeio.anytype.presentation.sets.model.SortingExpression
|
||||
import com.anytypeio.anytype.presentation.sets.model.Viewer
|
||||
import com.anytypeio.anytype.presentation.util.CoroutinesTestRule
|
||||
|
@ -74,7 +75,7 @@ class ObjectSetUpdateViewerSortTest : ObjectSetViewModelTestSetup() {
|
|||
context = root,
|
||||
block = doc.dv.id,
|
||||
view = doc.viewer2.id,
|
||||
limit = 0,
|
||||
limit = ObjectSetConfig.DEFAULT_LIMIT,
|
||||
offset = 0
|
||||
)
|
||||
)
|
||||
|
|
|
@ -7,6 +7,7 @@ import com.anytypeio.anytype.core_models.Event
|
|||
import com.anytypeio.anytype.domain.dataview.interactor.SetActiveViewer
|
||||
import com.anytypeio.anytype.domain.dataview.interactor.UpdateDataViewViewer
|
||||
import com.anytypeio.anytype.presentation.TypicalTwoRecordObjectSet
|
||||
import com.anytypeio.anytype.presentation.relations.ObjectSetConfig
|
||||
import com.anytypeio.anytype.presentation.sets.model.FilterExpression
|
||||
import com.anytypeio.anytype.presentation.sets.model.FilterValue
|
||||
import com.anytypeio.anytype.presentation.sets.model.Viewer
|
||||
|
@ -74,7 +75,7 @@ class ObjectSetViewerFilterTest : ObjectSetViewModelTestSetup() {
|
|||
context = root,
|
||||
block = doc.dv.id,
|
||||
view = doc.viewer2.id,
|
||||
limit = 0,
|
||||
limit = ObjectSetConfig.DEFAULT_LIMIT,
|
||||
offset = 0
|
||||
)
|
||||
)
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue