mirror of
https://github.com/anyproto/anytype-kotlin.git
synced 2025-06-08 05:47:05 +09:00
DROID-2727 Version history | Enable version history for sets and collections (#1542)
This commit is contained in:
parent
23706d1fe8
commit
0544fb7cf9
8 changed files with 348 additions and 52 deletions
|
@ -4,10 +4,13 @@ import androidx.lifecycle.ViewModelProvider
|
|||
import com.anytypeio.anytype.core_utils.di.scope.PerModal
|
||||
import com.anytypeio.anytype.presentation.history.VersionHistoryVMFactory
|
||||
import com.anytypeio.anytype.presentation.history.VersionHistoryViewModel
|
||||
import com.anytypeio.anytype.presentation.sets.state.DefaultObjectStateReducer
|
||||
import com.anytypeio.anytype.presentation.sets.state.ObjectStateReducer
|
||||
import com.anytypeio.anytype.ui.history.VersionHistoryFragment
|
||||
import dagger.Binds
|
||||
import dagger.BindsInstance
|
||||
import dagger.Module
|
||||
import dagger.Provides
|
||||
import dagger.Subcomponent
|
||||
|
||||
@Subcomponent(
|
||||
|
@ -32,6 +35,11 @@ interface VersionHistoryComponent {
|
|||
@Module
|
||||
object VersionHistoryModule {
|
||||
|
||||
@JvmStatic
|
||||
@Provides
|
||||
@PerModal
|
||||
fun provideObjectStateReducer(): ObjectStateReducer = DefaultObjectStateReducer()
|
||||
|
||||
@Module
|
||||
interface Declarations {
|
||||
|
||||
|
|
|
@ -19,6 +19,7 @@ import com.anytypeio.anytype.R
|
|||
import com.anytypeio.anytype.core_models.Id
|
||||
import com.anytypeio.anytype.core_models.Url
|
||||
import com.anytypeio.anytype.core_models.primitives.SpaceId
|
||||
import com.anytypeio.anytype.core_ui.features.dataview.ViewerGridHeaderAdapter
|
||||
import com.anytypeio.anytype.core_ui.features.editor.BlockAdapter
|
||||
import com.anytypeio.anytype.core_ui.features.editor.DragAndDropAdapterDelegate
|
||||
import com.anytypeio.anytype.core_ui.features.history.VersionHistoryPreviewScreen
|
||||
|
@ -71,6 +72,7 @@ class VersionHistoryFragment : BaseBottomSheetComposeFragment() {
|
|||
vm.proceedWithClick(it)
|
||||
}
|
||||
)
|
||||
private val viewerGridHeaderAdapter by lazy { ViewerGridHeaderAdapter() }
|
||||
|
||||
@OptIn(ExperimentalMaterialNavigationApi::class)
|
||||
override fun onCreateView(
|
||||
|
@ -120,7 +122,8 @@ class VersionHistoryFragment : BaseBottomSheetComposeFragment() {
|
|||
state = vm.previewViewState.collectAsStateWithLifecycle().value,
|
||||
editorAdapter = editorAdapter,
|
||||
onDismiss = vm::proceedWithHidePreview,
|
||||
onRestore = vm::proceedWithRestore
|
||||
onRestore = vm::proceedWithRestore,
|
||||
gridAdapter = viewerGridHeaderAdapter
|
||||
)
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,5 +1,8 @@
|
|||
package com.anytypeio.anytype.core_ui.features.history
|
||||
|
||||
import android.view.LayoutInflater
|
||||
import android.widget.HorizontalScrollView
|
||||
import android.widget.TextView
|
||||
import androidx.compose.foundation.BorderStroke
|
||||
import androidx.compose.foundation.background
|
||||
import androidx.compose.foundation.border
|
||||
|
@ -39,6 +42,7 @@ import androidx.compose.ui.viewinterop.AndroidView
|
|||
import androidx.recyclerview.widget.LinearLayoutManager
|
||||
import androidx.recyclerview.widget.RecyclerView
|
||||
import com.anytypeio.anytype.core_ui.R
|
||||
import com.anytypeio.anytype.core_ui.features.dataview.ViewerGridHeaderAdapter
|
||||
import com.anytypeio.anytype.core_ui.features.editor.BlockAdapter
|
||||
import com.anytypeio.anytype.core_ui.foundation.Dragger
|
||||
import com.anytypeio.anytype.core_ui.views.ButtonPrimary
|
||||
|
@ -55,7 +59,8 @@ fun VersionHistoryPreviewScreen(
|
|||
state: VersionHistoryPreviewScreen,
|
||||
onDismiss: () -> Unit,
|
||||
onRestore: () -> Unit,
|
||||
editorAdapter: BlockAdapter
|
||||
editorAdapter: BlockAdapter,
|
||||
gridAdapter: ViewerGridHeaderAdapter
|
||||
) {
|
||||
val sheetState = rememberModalBottomSheetState(skipPartiallyExpanded = true)
|
||||
val versionTitle = remember { mutableStateOf("") }
|
||||
|
@ -87,21 +92,22 @@ fun VersionHistoryPreviewScreen(
|
|||
.padding(vertical = 6.dp)
|
||||
)
|
||||
Header(title = versionTitle.value, icon = versionIcon.value)
|
||||
AndroidView(
|
||||
factory = { context ->
|
||||
RecyclerView(context).apply {
|
||||
layoutParams = RecyclerView.LayoutParams(
|
||||
RecyclerView.LayoutParams.MATCH_PARENT,
|
||||
RecyclerView.LayoutParams.MATCH_PARENT
|
||||
)
|
||||
layoutManager = LinearLayoutManager(context)
|
||||
adapter = editorAdapter
|
||||
}
|
||||
},
|
||||
update = {
|
||||
editorAdapter.updateWithDiffUtil(state.blocks)
|
||||
when (state) {
|
||||
is VersionHistoryPreviewScreen.Success.Editor -> {
|
||||
EditorScreen(
|
||||
editorAdapter = editorAdapter,
|
||||
state = state
|
||||
)
|
||||
}
|
||||
)
|
||||
|
||||
is VersionHistoryPreviewScreen.Success.Set -> {
|
||||
ObjectSetScreen(
|
||||
editorAdapter = editorAdapter,
|
||||
state = state,
|
||||
gridAdapter = gridAdapter
|
||||
)
|
||||
}
|
||||
}
|
||||
}
|
||||
Buttons(onDismiss = onDismiss, onRestore = onRestore)
|
||||
}
|
||||
|
@ -109,6 +115,62 @@ fun VersionHistoryPreviewScreen(
|
|||
}
|
||||
}
|
||||
|
||||
@Composable
|
||||
private fun EditorScreen(
|
||||
editorAdapter: BlockAdapter,
|
||||
state: VersionHistoryPreviewScreen.Success.Editor
|
||||
) {
|
||||
AndroidView(
|
||||
factory = { context ->
|
||||
RecyclerView(context).apply {
|
||||
layoutParams = RecyclerView.LayoutParams(
|
||||
RecyclerView.LayoutParams.MATCH_PARENT,
|
||||
RecyclerView.LayoutParams.MATCH_PARENT
|
||||
)
|
||||
layoutManager = LinearLayoutManager(context)
|
||||
adapter = editorAdapter
|
||||
}
|
||||
},
|
||||
update = {
|
||||
editorAdapter.updateWithDiffUtil(state.blocks)
|
||||
}
|
||||
)
|
||||
}
|
||||
|
||||
@Composable
|
||||
private fun ObjectSetScreen(
|
||||
editorAdapter: BlockAdapter,
|
||||
gridAdapter: ViewerGridHeaderAdapter,
|
||||
state: VersionHistoryPreviewScreen.Success.Set
|
||||
) {
|
||||
AndroidView(
|
||||
factory = { context ->
|
||||
val view = LayoutInflater.from(context).inflate(
|
||||
R.layout.layout_version_history_set,
|
||||
null
|
||||
).apply {
|
||||
findViewById<RecyclerView>(R.id.objectHeader).apply {
|
||||
layoutManager = LinearLayoutManager(context, RecyclerView.VERTICAL, false)
|
||||
adapter = editorAdapter
|
||||
}
|
||||
findViewById<HorizontalScrollView>(R.id.gridContainer).apply {
|
||||
findViewById<RecyclerView>(R.id.rvHeader).apply {
|
||||
adapter = gridAdapter
|
||||
}
|
||||
}
|
||||
}
|
||||
view
|
||||
},
|
||||
update = {
|
||||
it.findViewById<TextView>(R.id.tvCurrentViewerName).apply {
|
||||
text = state.viewer?.name
|
||||
}
|
||||
editorAdapter.updateWithDiffUtil(state.blocks)
|
||||
gridAdapter.submitList(state.viewer?.columns)
|
||||
}
|
||||
)
|
||||
}
|
||||
|
||||
@Composable
|
||||
private fun Header(title: String, icon: ObjectIcon?) {
|
||||
Box(
|
||||
|
@ -165,14 +227,18 @@ private fun BoxScope.Buttons(
|
|||
text = stringResource(id = R.string.cancel),
|
||||
onClick = onDismiss,
|
||||
size = ButtonSize.LargeSecondary,
|
||||
modifier = Modifier.padding(top = 16.dp, bottom = 32.dp).weight(1.0f)
|
||||
modifier = Modifier
|
||||
.padding(top = 16.dp, bottom = 32.dp)
|
||||
.weight(1.0f)
|
||||
)
|
||||
Spacer(modifier = Modifier.width(9.dp))
|
||||
ButtonPrimary(
|
||||
text = stringResource(id = R.string.restore),
|
||||
onClick = onRestore,
|
||||
size = ButtonSize.Large,
|
||||
modifier = Modifier.padding(top = 16.dp, bottom = 32.dp).weight(1.0f)
|
||||
modifier = Modifier
|
||||
.padding(top = 16.dp, bottom = 32.dp)
|
||||
.weight(1.0f)
|
||||
)
|
||||
}
|
||||
}
|
50
core-ui/src/main/res/layout/layout_version_history_set.xml
Normal file
50
core-ui/src/main/res/layout/layout_version_history_set.xml
Normal file
|
@ -0,0 +1,50 @@
|
|||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
xmlns:app="http://schemas.android.com/apk/res-auto"
|
||||
xmlns:tools="http://schemas.android.com/tools"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:orientation="vertical">
|
||||
|
||||
<androidx.recyclerview.widget.RecyclerView
|
||||
android:id="@+id/objectHeader"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:orientation="vertical" />
|
||||
|
||||
<androidx.constraintlayout.widget.ConstraintLayout
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="@dimen/default_collection_dv_header_height">
|
||||
|
||||
<TextView
|
||||
android:id="@+id/tvCurrentViewerName"
|
||||
style="@style/ViewerTitleStyle"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="match_parent"
|
||||
android:layout_gravity="center_vertical"
|
||||
android:drawablePadding="2dp"
|
||||
android:gravity="center_vertical"
|
||||
android:paddingStart="@dimen/dp_20"
|
||||
app:drawableEndCompat="@drawable/ic_arrow_expand_dv_viewer"
|
||||
app:layout_constraintBottom_toBottomOf="parent"
|
||||
app:layout_constraintStart_toStartOf="parent"
|
||||
app:layout_constraintTop_toTopOf="parent"
|
||||
tools:text="All" />
|
||||
|
||||
<View
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="0.5dp"
|
||||
android:background="@color/shape_primary"
|
||||
app:layout_constraintBottom_toBottomOf="parent"
|
||||
app:layout_constraintEnd_toEndOf="parent"
|
||||
app:layout_constraintStart_toStartOf="parent" />
|
||||
|
||||
</androidx.constraintlayout.widget.ConstraintLayout>
|
||||
|
||||
<include
|
||||
android:id="@+id/gridContainer"
|
||||
layout="@layout/item_viewer_container"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content" />
|
||||
|
||||
</LinearLayout>
|
|
@ -7,4 +7,8 @@
|
|||
<item name="menuChangeType" type="id"/>
|
||||
<item name="menuOpenSet" type="id"/>
|
||||
<item name="menuCreateSet" type="id"/>
|
||||
|
||||
<item name="object_set_header" type="id"/>
|
||||
<item name="featuredRelationsWidget" type="id"/>
|
||||
|
||||
</resources>
|
|
@ -9,9 +9,12 @@ import com.anytypeio.anytype.domain.history.ShowVersion
|
|||
import com.anytypeio.anytype.domain.misc.DateProvider
|
||||
import com.anytypeio.anytype.domain.misc.LocaleProvider
|
||||
import com.anytypeio.anytype.domain.misc.UrlBuilder
|
||||
import com.anytypeio.anytype.domain.objects.StoreOfRelations
|
||||
import com.anytypeio.anytype.domain.search.SearchObjects
|
||||
import com.anytypeio.anytype.presentation.editor.cover.CoverImageHashProvider
|
||||
import com.anytypeio.anytype.presentation.editor.render.DefaultBlockViewRenderer
|
||||
import com.anytypeio.anytype.presentation.history.VersionHistoryViewModel.VmParams
|
||||
import com.anytypeio.anytype.presentation.sets.state.ObjectStateReducer
|
||||
import javax.inject.Inject
|
||||
|
||||
class VersionHistoryVMFactory @Inject constructor(
|
||||
|
@ -24,7 +27,10 @@ class VersionHistoryVMFactory @Inject constructor(
|
|||
private val urlBuilder: UrlBuilder,
|
||||
private val showVersion: ShowVersion,
|
||||
private val setVersion: SetVersion,
|
||||
private val renderer: DefaultBlockViewRenderer
|
||||
private val renderer: DefaultBlockViewRenderer,
|
||||
private val setStateReducer: ObjectStateReducer,
|
||||
private val coverImageHashProvider: CoverImageHashProvider,
|
||||
private val storeOfRelations: StoreOfRelations
|
||||
) : ViewModelProvider.Factory {
|
||||
|
||||
@Suppress("UNCHECKED_CAST")
|
||||
|
@ -39,7 +45,10 @@ class VersionHistoryVMFactory @Inject constructor(
|
|||
urlBuilder = urlBuilder,
|
||||
showVersion = showVersion,
|
||||
renderer = renderer,
|
||||
setVersion = setVersion
|
||||
setVersion = setVersion,
|
||||
setStateReducer = setStateReducer,
|
||||
coverImageHashProvider = coverImageHashProvider,
|
||||
storeOfRelations = storeOfRelations
|
||||
) as T
|
||||
}
|
||||
}
|
|
@ -6,6 +6,7 @@ import com.anytypeio.anytype.analytics.base.Analytics
|
|||
import com.anytypeio.anytype.core_models.Event
|
||||
import com.anytypeio.anytype.core_models.Id
|
||||
import com.anytypeio.anytype.core_models.ObjectWrapper
|
||||
import com.anytypeio.anytype.core_models.Payload
|
||||
import com.anytypeio.anytype.core_models.Relation
|
||||
import com.anytypeio.anytype.core_models.RelationFormat
|
||||
import com.anytypeio.anytype.core_models.ext.asMap
|
||||
|
@ -22,9 +23,11 @@ import com.anytypeio.anytype.domain.history.ShowVersion
|
|||
import com.anytypeio.anytype.domain.misc.DateProvider
|
||||
import com.anytypeio.anytype.domain.misc.LocaleProvider
|
||||
import com.anytypeio.anytype.domain.misc.UrlBuilder
|
||||
import com.anytypeio.anytype.domain.objects.StoreOfRelations
|
||||
import com.anytypeio.anytype.domain.search.SearchObjects
|
||||
import com.anytypeio.anytype.presentation.editor.Editor.Mode
|
||||
import com.anytypeio.anytype.presentation.editor.EditorViewModel.Companion.INITIAL_INDENT
|
||||
import com.anytypeio.anytype.presentation.editor.cover.CoverImageHashProvider
|
||||
import com.anytypeio.anytype.presentation.editor.editor.listener.ListenerType
|
||||
import com.anytypeio.anytype.presentation.editor.editor.model.BlockView
|
||||
import com.anytypeio.anytype.presentation.editor.render.BlockViewRenderer
|
||||
|
@ -33,9 +36,15 @@ import com.anytypeio.anytype.presentation.extension.sendAnalyticsScreenVersionPr
|
|||
import com.anytypeio.anytype.presentation.extension.sendAnalyticsShowVersionHistoryScreen
|
||||
import com.anytypeio.anytype.presentation.extension.sendAnalyticsVersionHistoryRestore
|
||||
import com.anytypeio.anytype.presentation.history.VersionHistoryGroup.GroupTitle
|
||||
import com.anytypeio.anytype.presentation.mapper.toViewerColumns
|
||||
import com.anytypeio.anytype.presentation.objects.ObjectIcon
|
||||
import com.anytypeio.anytype.presentation.relations.ObjectSetConfig
|
||||
import com.anytypeio.anytype.presentation.relations.getRelationFormat
|
||||
import com.anytypeio.anytype.presentation.search.ObjectSearchConstants
|
||||
import com.anytypeio.anytype.presentation.sets.model.Viewer
|
||||
import com.anytypeio.anytype.presentation.sets.state.ObjectState
|
||||
import com.anytypeio.anytype.presentation.sets.state.ObjectStateReducer
|
||||
import com.anytypeio.anytype.presentation.sets.viewerByIdOrFirst
|
||||
import java.time.Instant
|
||||
import java.time.LocalDate
|
||||
import java.time.ZoneId
|
||||
|
@ -45,6 +54,8 @@ import kotlinx.coroutines.flow.MutableStateFlow
|
|||
import kotlinx.coroutines.flow.asStateFlow
|
||||
import kotlinx.coroutines.flow.collectLatest
|
||||
import kotlinx.coroutines.flow.combine
|
||||
import kotlinx.coroutines.flow.distinctUntilChanged
|
||||
import kotlinx.coroutines.flow.filterIsInstance
|
||||
import kotlinx.coroutines.launch
|
||||
import timber.log.Timber
|
||||
|
||||
|
@ -58,7 +69,10 @@ class VersionHistoryViewModel(
|
|||
private val urlBuilder: UrlBuilder,
|
||||
private val showVersion: ShowVersion,
|
||||
private val setVersion: SetVersion,
|
||||
private val renderer: DefaultBlockViewRenderer
|
||||
private val renderer: DefaultBlockViewRenderer,
|
||||
private val setStateReducer: ObjectStateReducer,
|
||||
private val coverImageHashProvider: CoverImageHashProvider,
|
||||
private val storeOfRelations: StoreOfRelations
|
||||
) : ViewModel(), BlockViewRenderer by renderer {
|
||||
|
||||
private val _viewState = MutableStateFlow<VersionHistoryState>(VersionHistoryState.Loading)
|
||||
|
@ -76,8 +90,13 @@ class VersionHistoryViewModel(
|
|||
val latestVisibleVersionId = MutableStateFlow("")
|
||||
private val _versions = MutableStateFlow<List<Version>>(emptyList())
|
||||
|
||||
private val defaultPayloadConsumer: suspend (Payload) -> Unit = { payload ->
|
||||
setStateReducer.dispatch(payload.events)
|
||||
}
|
||||
|
||||
init {
|
||||
Timber.d("VersionHistoryViewModel created")
|
||||
viewModelScope.launch { setStateReducer.run() }
|
||||
getSpaceMembers()
|
||||
getHistoryVersions(objectId = vmParams.objectId)
|
||||
viewModelScope.launch {
|
||||
|
@ -95,6 +114,34 @@ class VersionHistoryViewModel(
|
|||
}
|
||||
}
|
||||
}
|
||||
viewModelScope.launch {
|
||||
setStateReducer.state
|
||||
.filterIsInstance<ObjectState.DataView>()
|
||||
.distinctUntilChanged()
|
||||
.collectLatest { state ->
|
||||
val viewer = mapToViewer(state)
|
||||
when (val currentState = _previewViewState.value) {
|
||||
VersionHistoryPreviewScreen.Loading -> {
|
||||
_previewViewState.value = VersionHistoryPreviewScreen.Success.Set(
|
||||
versionId = "",
|
||||
blocks = emptyList(),
|
||||
dateFormatted = "",
|
||||
timeFormatted = "",
|
||||
viewer = viewer,
|
||||
icon = null
|
||||
)
|
||||
}
|
||||
is VersionHistoryPreviewScreen.Success.Set -> {
|
||||
_previewViewState.value = currentState.copy(
|
||||
viewer = viewer
|
||||
)
|
||||
}
|
||||
else -> {
|
||||
Timber.d("Version preview state is not loading or success.set, skipping state update")
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
fun onStart() {
|
||||
|
@ -142,7 +189,9 @@ class VersionHistoryViewModel(
|
|||
}
|
||||
}
|
||||
|
||||
else -> {}
|
||||
else -> {
|
||||
Timber.d("No interaction allowed with this listener type: $click")
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -153,7 +202,7 @@ class VersionHistoryViewModel(
|
|||
) {
|
||||
val currentState =
|
||||
(_previewViewState.value as? VersionHistoryPreviewScreen.Success) ?: return
|
||||
val isSet = currentState.isSet
|
||||
val isSet = currentState is VersionHistoryPreviewScreen.Success.Set
|
||||
when (relationFormat) {
|
||||
RelationFormat.SHORT_TEXT,
|
||||
RelationFormat.LONG_TEXT,
|
||||
|
@ -468,27 +517,13 @@ class VersionHistoryViewModel(
|
|||
.first()
|
||||
val obj =
|
||||
ObjectWrapper.Basic(event.details.details[vmParams.objectId]?.map.orEmpty())
|
||||
val root = event.blocks.first { it.id == vmParams.objectId }
|
||||
val blocks = event.blocks.asMap().render(
|
||||
mode = Mode.Read,
|
||||
root = root,
|
||||
focus = Editor.Focus.empty(),
|
||||
anchor = vmParams.objectId,
|
||||
indent = INITIAL_INDENT,
|
||||
details = event.details,
|
||||
relationLinks = event.relationLinks,
|
||||
restrictions = event.objectRestrictions,
|
||||
selection = emptySet()
|
||||
)
|
||||
val currentState = _previewViewState.value
|
||||
if (currentState !is VersionHistoryPreviewScreen.Hidden) {
|
||||
_previewViewState.value = VersionHistoryPreviewScreen.Success(
|
||||
versionId = item.id,
|
||||
blocks = blocks,
|
||||
dateFormatted = item.dateFormatted,
|
||||
timeFormatted = item.timeFormatted,
|
||||
icon = item.icon,
|
||||
isSet = obj.layout.isDataView()
|
||||
parseObject(
|
||||
payload = payload,
|
||||
event = event,
|
||||
item = item,
|
||||
obj = obj
|
||||
)
|
||||
}
|
||||
}
|
||||
|
@ -496,6 +531,100 @@ class VersionHistoryViewModel(
|
|||
)
|
||||
}
|
||||
|
||||
private suspend fun parseObject(
|
||||
payload: Payload,
|
||||
//TODO: Refactoring: update ShowVersion response to include ObjectView instead of Payload
|
||||
event: Event.Command.ShowObject,
|
||||
item: VersionHistoryGroup.Item,
|
||||
obj: ObjectWrapper.Basic
|
||||
) {
|
||||
if (obj.layout.isDataView()) {
|
||||
defaultPayloadConsumer(payload)
|
||||
val root = event.blocks.first { it.id == vmParams.objectId }
|
||||
val blocks = event.blocks.asMap().render(
|
||||
mode = Mode.Read,
|
||||
root = root,
|
||||
focus = Editor.Focus.empty(),
|
||||
anchor = vmParams.objectId,
|
||||
indent = INITIAL_INDENT,
|
||||
details = event.details,
|
||||
relationLinks = event.relationLinks,
|
||||
restrictions = event.objectRestrictions,
|
||||
selection = emptySet()
|
||||
).filterNot { it is BlockView.DataView }
|
||||
when (val currentState = _previewViewState.value) {
|
||||
VersionHistoryPreviewScreen.Loading -> {
|
||||
_previewViewState.value = VersionHistoryPreviewScreen.Success.Set(
|
||||
versionId = item.id,
|
||||
blocks = blocks,
|
||||
dateFormatted = item.dateFormatted,
|
||||
timeFormatted = item.timeFormatted,
|
||||
viewer = null,
|
||||
icon = item.icon
|
||||
)
|
||||
}
|
||||
is VersionHistoryPreviewScreen.Success.Set -> {
|
||||
_previewViewState.value = currentState.copy(
|
||||
versionId = item.id,
|
||||
dateFormatted = item.dateFormatted,
|
||||
timeFormatted = item.timeFormatted,
|
||||
icon = item.icon,
|
||||
blocks = blocks
|
||||
)
|
||||
}
|
||||
else -> {
|
||||
Timber.d("Version preview state is not loading or success.set, skipping state update")
|
||||
}
|
||||
}
|
||||
} else {
|
||||
val root = event.blocks.first { it.id == vmParams.objectId }
|
||||
val blocks = event.blocks.asMap().render(
|
||||
mode = Mode.Read,
|
||||
root = root,
|
||||
focus = Editor.Focus.empty(),
|
||||
anchor = vmParams.objectId,
|
||||
indent = INITIAL_INDENT,
|
||||
details = event.details,
|
||||
relationLinks = event.relationLinks,
|
||||
restrictions = event.objectRestrictions,
|
||||
selection = emptySet()
|
||||
)
|
||||
_previewViewState.value = VersionHistoryPreviewScreen.Success.Editor(
|
||||
versionId = item.id,
|
||||
blocks = blocks,
|
||||
dateFormatted = item.dateFormatted,
|
||||
timeFormatted = item.timeFormatted,
|
||||
icon = item.icon
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
private suspend fun mapToViewer(objectState: ObjectState.DataView): Viewer.GridView? {
|
||||
val dvViewer = objectState.viewerByIdOrFirst(null)
|
||||
val viewerRelations = dvViewer?.viewerRelations ?: return null
|
||||
|
||||
val vmap = viewerRelations.associateBy { it.key }
|
||||
|
||||
val dataViewRelations = objectState.dataViewContent.relationLinks.mapNotNull {
|
||||
storeOfRelations.getByKey(it.key)
|
||||
}
|
||||
val visibleRelations = dataViewRelations.filter { relation ->
|
||||
val vr = vmap[relation.key]
|
||||
vr?.isVisible ?: false
|
||||
}
|
||||
val columns = viewerRelations.toViewerColumns(
|
||||
relations = visibleRelations,
|
||||
filterBy = listOf(ObjectSetConfig.NAME_KEY)
|
||||
)
|
||||
|
||||
return Viewer.GridView(
|
||||
id = dvViewer.id,
|
||||
name = dvViewer.name,
|
||||
columns = columns,
|
||||
rows = emptyList()
|
||||
)
|
||||
}
|
||||
|
||||
data class VmParams(
|
||||
val objectId: Id,
|
||||
val spaceId: SpaceId
|
||||
|
@ -536,15 +665,30 @@ sealed class VersionHistoryState {
|
|||
sealed class VersionHistoryPreviewScreen {
|
||||
data object Hidden : VersionHistoryPreviewScreen()
|
||||
data object Loading : VersionHistoryPreviewScreen()
|
||||
data class Success(
|
||||
val versionId: Id,
|
||||
val blocks: List<BlockView>,
|
||||
val dateFormatted: String,
|
||||
val timeFormatted: String,
|
||||
val icon: ObjectIcon?,
|
||||
val isSet: Boolean
|
||||
) :
|
||||
VersionHistoryPreviewScreen()
|
||||
sealed class Success : VersionHistoryPreviewScreen() {
|
||||
|
||||
abstract val versionId: Id
|
||||
abstract val icon: ObjectIcon?
|
||||
abstract val dateFormatted: String
|
||||
abstract val timeFormatted: String
|
||||
|
||||
data class Editor(
|
||||
override val versionId: Id,
|
||||
override val dateFormatted: String,
|
||||
override val timeFormatted: String,
|
||||
override val icon: ObjectIcon?,
|
||||
val blocks: List<BlockView>
|
||||
) : Success()
|
||||
|
||||
data class Set(
|
||||
override val versionId: Id,
|
||||
override val dateFormatted: String,
|
||||
override val timeFormatted: String,
|
||||
override val icon: ObjectIcon?,
|
||||
val viewer: Viewer.GridView?,
|
||||
val blocks: List<BlockView>
|
||||
) : Success()
|
||||
}
|
||||
|
||||
data class Error(val message: String) : VersionHistoryPreviewScreen()
|
||||
}
|
||||
|
|
|
@ -18,13 +18,16 @@ import com.anytypeio.anytype.domain.history.ShowVersion
|
|||
import com.anytypeio.anytype.domain.misc.DateProvider
|
||||
import com.anytypeio.anytype.domain.misc.LocaleProvider
|
||||
import com.anytypeio.anytype.domain.misc.UrlBuilder
|
||||
import com.anytypeio.anytype.domain.objects.StoreOfRelations
|
||||
import com.anytypeio.anytype.domain.search.SearchObjects
|
||||
import com.anytypeio.anytype.domain.workspace.SpaceManager
|
||||
import com.anytypeio.anytype.presentation.editor.cover.CoverImageHashProvider
|
||||
import com.anytypeio.anytype.presentation.editor.render.DefaultBlockViewRenderer
|
||||
import com.anytypeio.anytype.presentation.history.VersionHistoryViewModel.Companion.GROUP_DATE_FORMAT_OTHER_YEAR
|
||||
import com.anytypeio.anytype.presentation.history.VersionHistoryViewModel.Companion.VERSIONS_MAX_LIMIT
|
||||
import com.anytypeio.anytype.presentation.objects.ObjectIcon
|
||||
import com.anytypeio.anytype.presentation.search.ObjectSearchConstants
|
||||
import com.anytypeio.anytype.presentation.sets.state.DefaultObjectStateReducer
|
||||
import com.anytypeio.anytype.presentation.widgets.collection.DateProviderImpl
|
||||
import java.time.ZoneId
|
||||
import java.util.Locale
|
||||
|
@ -99,6 +102,12 @@ class VersionHistoryViewModelTest {
|
|||
@Mock
|
||||
lateinit var renderer: DefaultBlockViewRenderer
|
||||
|
||||
@Mock
|
||||
lateinit var storeOfRelations: StoreOfRelations
|
||||
|
||||
@Mock
|
||||
lateinit var coverImageHashProvider: CoverImageHashProvider
|
||||
|
||||
lateinit var spaceManager: SpaceManager
|
||||
|
||||
lateinit var vm: VersionHistoryViewModel
|
||||
|
@ -544,7 +553,10 @@ class VersionHistoryViewModelTest {
|
|||
urlBuilder = urlBuilder,
|
||||
renderer = renderer,
|
||||
setVersion = setVersion,
|
||||
showVersion = showVersion
|
||||
showVersion = showVersion,
|
||||
setStateReducer = DefaultObjectStateReducer(),
|
||||
storeOfRelations = storeOfRelations,
|
||||
coverImageHashProvider = coverImageHashProvider
|
||||
)
|
||||
}
|
||||
}
|
Loading…
Add table
Add a link
Reference in a new issue