mirror of
https://github.com/anyproto/anytype-kotlin.git
synced 2025-06-08 05:47:05 +09:00
DROID-2726 Version history | Show relation values (#1474)
This commit is contained in:
parent
c593cceeb8
commit
78570899e1
7 changed files with 201 additions and 38 deletions
|
@ -39,6 +39,7 @@ import com.anytypeio.anytype.ui.linking.BacklinkOrAddToObjectFragment
|
|||
import com.anytypeio.anytype.ui.moving.OnMoveToAction
|
||||
import com.anytypeio.anytype.ui.relations.ObjectRelationListFragment
|
||||
import com.google.android.material.snackbar.Snackbar
|
||||
import timber.log.Timber
|
||||
|
||||
abstract class ObjectMenuBaseFragment :
|
||||
BaseBottomSheetFragment<FragmentObjectMenuBinding>(),
|
||||
|
@ -177,6 +178,8 @@ abstract class ObjectMenuBaseFragment :
|
|||
spaceId = space
|
||||
)
|
||||
)
|
||||
}.onFailure {
|
||||
Timber.e(it, "Failed to open history screen")
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -25,13 +25,19 @@ import com.anytypeio.anytype.core_ui.features.history.VersionHistoryPreviewScree
|
|||
import com.anytypeio.anytype.core_ui.features.history.VersionHistoryScreen
|
||||
import com.anytypeio.anytype.core_ui.tools.ClipboardInterceptor
|
||||
import com.anytypeio.anytype.core_utils.ext.argString
|
||||
import com.anytypeio.anytype.core_utils.ext.safeNavigate
|
||||
import com.anytypeio.anytype.core_utils.ext.setupBottomSheetBehavior
|
||||
import com.anytypeio.anytype.core_utils.ext.subscribe
|
||||
import com.anytypeio.anytype.core_utils.ui.BaseBottomSheetComposeFragment
|
||||
import com.anytypeio.anytype.di.common.componentManager
|
||||
import com.anytypeio.anytype.presentation.history.VersionGroupNavigation
|
||||
import com.anytypeio.anytype.presentation.history.VersionHistoryVMFactory
|
||||
import com.anytypeio.anytype.presentation.history.VersionHistoryViewModel
|
||||
import com.anytypeio.anytype.presentation.history.VersionHistoryViewModel.Command
|
||||
import com.anytypeio.anytype.presentation.relations.value.tagstatus.RelationContext
|
||||
import com.anytypeio.anytype.ui.relations.RelationDateValueFragment
|
||||
import com.anytypeio.anytype.ui.relations.RelationTextValueFragment
|
||||
import com.anytypeio.anytype.ui.relations.value.ObjectValueFragment
|
||||
import com.anytypeio.anytype.ui.relations.value.TagOrStatusValueFragment
|
||||
import com.google.accompanist.navigation.material.BottomSheetNavigator
|
||||
import com.google.accompanist.navigation.material.ExperimentalMaterialNavigationApi
|
||||
import com.google.accompanist.navigation.material.ModalBottomSheetLayout
|
||||
|
@ -61,6 +67,9 @@ class VersionHistoryFragment : BaseBottomSheetComposeFragment() {
|
|||
onDragListener = { _, _ -> false },
|
||||
lifecycle = lifecycle,
|
||||
dragAndDropSelector = DragAndDropAdapterDelegate(),
|
||||
onClickListener = {
|
||||
vm.proceedWithClick(it)
|
||||
}
|
||||
)
|
||||
|
||||
@OptIn(ExperimentalMaterialNavigationApi::class)
|
||||
|
@ -95,15 +104,15 @@ class VersionHistoryFragment : BaseBottomSheetComposeFragment() {
|
|||
private fun NavigationGraph(navController: NavHostController) {
|
||||
NavHost(
|
||||
navController = navController,
|
||||
startDestination = VersionGroupNavigation.Main.route
|
||||
startDestination = Command.Main.route
|
||||
) {
|
||||
composable(VersionGroupNavigation.Main.route) {
|
||||
composable(Command.Main.route) {
|
||||
VersionHistoryScreen(
|
||||
state = vm.viewState.collectAsStateWithLifecycle().value,
|
||||
onItemClick = vm::onGroupItemClicked
|
||||
)
|
||||
}
|
||||
bottomSheet(VersionGroupNavigation.VersionPreview.route) {
|
||||
bottomSheet(Command.VersionPreview.route) {
|
||||
VersionHistoryPreviewScreen(
|
||||
state = vm.previewViewState.collectAsStateWithLifecycle().value,
|
||||
editorAdapter = editorAdapter,
|
||||
|
@ -118,20 +127,86 @@ class VersionHistoryFragment : BaseBottomSheetComposeFragment() {
|
|||
super.onViewCreated(view, savedInstanceState)
|
||||
setupBottomSheetBehavior(DEFAULT_PADDING_TOP)
|
||||
subscribe(vm.navigation){ navigation ->
|
||||
when(navigation){
|
||||
is VersionGroupNavigation.VersionPreview -> {
|
||||
navComposeController.navigate(VersionGroupNavigation.VersionPreview.route)
|
||||
}
|
||||
VersionGroupNavigation.Main -> {
|
||||
navComposeController.popBackStack()
|
||||
}
|
||||
VersionGroupNavigation.ExitToObject -> {
|
||||
findNavController().popBackStack(R.id.objectMenuScreen, true)
|
||||
}
|
||||
when (navigation) {
|
||||
is Command.VersionPreview -> navigateToVersionPreview()
|
||||
Command.Main -> navComposeController.popBackStack()
|
||||
Command.ExitToObject -> exitToObjectMenu()
|
||||
is Command.RelationMultiSelect -> navigateToRelationMultiSelect(navigation)
|
||||
is Command.RelationDate -> navigateToRelationDate(navigation)
|
||||
is Command.RelationObject -> navigateToRelationObject(navigation)
|
||||
is Command.RelationText -> navigateToRelationText(navigation)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private fun navigateToVersionPreview() {
|
||||
navComposeController.navigate(Command.VersionPreview.route)
|
||||
}
|
||||
|
||||
private fun exitToObjectMenu() {
|
||||
findNavController().popBackStack(R.id.objectMenuScreen, true)
|
||||
}
|
||||
|
||||
private fun navigateToRelationMultiSelect(navigation: Command.RelationMultiSelect) {
|
||||
val relationContext = if (navigation.isSet) RelationContext.OBJECT_SET else RelationContext.OBJECT
|
||||
val bundle = TagOrStatusValueFragment.args(
|
||||
ctx = ctx,
|
||||
space = spaceId,
|
||||
obj = ctx,
|
||||
relation = navigation.relationKey.key,
|
||||
isLocked = true,
|
||||
context = relationContext
|
||||
)
|
||||
findNavController().safeNavigate(
|
||||
R.id.versionHistoryScreen,
|
||||
R.id.nav_relations,
|
||||
bundle
|
||||
)
|
||||
}
|
||||
|
||||
private fun navigateToRelationDate(navigation: Command.RelationDate) {
|
||||
val relationContext = if (navigation.isSet) RelationDateValueFragment.FLOW_SET_OR_COLLECTION else RelationDateValueFragment.FLOW_DEFAULT
|
||||
val fr = RelationDateValueFragment.new(
|
||||
ctx = ctx,
|
||||
space = spaceId,
|
||||
relationKey = navigation.relationKey.key,
|
||||
objectId = ctx,
|
||||
flow = relationContext,
|
||||
isLocked = true
|
||||
)
|
||||
fr.showChildFragment()
|
||||
}
|
||||
|
||||
private fun navigateToRelationObject(navigation: Command.RelationObject) {
|
||||
val relationContext = if (navigation.isSet) RelationContext.OBJECT_SET else RelationContext.OBJECT
|
||||
findNavController().safeNavigate(
|
||||
R.id.versionHistoryScreen,
|
||||
R.id.objectValueScreen,
|
||||
ObjectValueFragment.args(
|
||||
ctx = ctx,
|
||||
space = spaceId,
|
||||
obj = ctx,
|
||||
relation = navigation.relationKey.key,
|
||||
isLocked = true,
|
||||
relationContext = relationContext
|
||||
)
|
||||
)
|
||||
}
|
||||
|
||||
private fun navigateToRelationText(navigation: Command.RelationText) {
|
||||
val relationContext =
|
||||
if (navigation.isSet) RelationTextValueFragment.FLOW_SET_OR_COLLECTION else RelationTextValueFragment.FLOW_DEFAULT
|
||||
val fr = RelationTextValueFragment.new(
|
||||
ctx = ctx,
|
||||
space = spaceId,
|
||||
relationKey = navigation.relationKey.key,
|
||||
objectId = ctx,
|
||||
flow = relationContext,
|
||||
isLocked = true
|
||||
)
|
||||
fr.showChildFragment()
|
||||
}
|
||||
|
||||
override fun onStart() {
|
||||
super.onStart()
|
||||
vm.onStart()
|
||||
|
|
|
@ -73,6 +73,11 @@
|
|||
android:id="@+id/objectValueScreen"
|
||||
android:name="com.anytypeio.anytype.ui.relations.value.ObjectValueFragment"
|
||||
android:label="Relation-Object-Value-Screen" />
|
||||
|
||||
<dialog
|
||||
android:id="@+id/versionHistoryScreen"
|
||||
android:name="com.anytypeio.anytype.ui.history.VersionHistoryFragment"
|
||||
android:label="Object-Version_history-Screen"/>
|
||||
</navigation>
|
||||
|
||||
<include app:graph="@navigation/nav_editor_modal" />
|
||||
|
@ -136,6 +141,10 @@
|
|||
android:id="@+id/objectValueScreen"
|
||||
android:name="com.anytypeio.anytype.ui.relations.value.ObjectValueFragment"
|
||||
android:label="Relation-Object-Value-Screen" />
|
||||
<dialog
|
||||
android:id="@+id/versionHistoryScreen"
|
||||
android:name="com.anytypeio.anytype.ui.history.VersionHistoryFragment"
|
||||
android:label="Set-Version_history-Screen"/>
|
||||
</navigation>
|
||||
|
||||
<fragment
|
||||
|
@ -248,10 +257,6 @@
|
|||
android:id="@+id/galleryInstallationScreen"
|
||||
android:name="com.anytypeio.anytype.ui.gallery.GalleryInstallationFragment" />
|
||||
|
||||
<dialog
|
||||
android:id="@+id/versionHistoryScreen"
|
||||
android:name="com.anytypeio.anytype.ui.history.VersionHistoryFragment" />
|
||||
|
||||
<fragment
|
||||
android:id="@+id/splashScreen"
|
||||
android:name="com.anytypeio.anytype.ui.splash.SplashFragment"
|
||||
|
|
|
@ -90,6 +90,10 @@ fun VersionHistoryPreviewScreen(
|
|||
AndroidView(
|
||||
factory = { context ->
|
||||
RecyclerView(context).apply {
|
||||
layoutParams = RecyclerView.LayoutParams(
|
||||
RecyclerView.LayoutParams.MATCH_PARENT,
|
||||
RecyclerView.LayoutParams.MATCH_PARENT
|
||||
)
|
||||
layoutManager = LinearLayoutManager(context)
|
||||
adapter = editorAdapter
|
||||
}
|
||||
|
|
|
@ -89,8 +89,7 @@ fun RelationsViewContent(
|
|||
LazyColumn(
|
||||
state = lazyListState,
|
||||
modifier = Modifier
|
||||
.fillMaxWidth()
|
||||
.wrapContentHeight()
|
||||
.fillMaxSize()
|
||||
) {
|
||||
itemsIndexed(
|
||||
items = state.items,
|
||||
|
|
|
@ -6,8 +6,12 @@ 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.Relation
|
||||
import com.anytypeio.anytype.core_models.RelationFormat
|
||||
import com.anytypeio.anytype.core_models.ext.asMap
|
||||
import com.anytypeio.anytype.core_models.history.Version
|
||||
import com.anytypeio.anytype.core_models.isDataView
|
||||
import com.anytypeio.anytype.core_models.primitives.RelationKey
|
||||
import com.anytypeio.anytype.core_models.primitives.SpaceId
|
||||
import com.anytypeio.anytype.core_models.primitives.TimeInSeconds
|
||||
import com.anytypeio.anytype.domain.base.fold
|
||||
|
@ -21,11 +25,13 @@ import com.anytypeio.anytype.domain.misc.UrlBuilder
|
|||
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.editor.listener.ListenerType
|
||||
import com.anytypeio.anytype.presentation.editor.editor.model.BlockView
|
||||
import com.anytypeio.anytype.presentation.editor.render.BlockViewRenderer
|
||||
import com.anytypeio.anytype.presentation.editor.render.DefaultBlockViewRenderer
|
||||
import com.anytypeio.anytype.presentation.history.VersionHistoryGroup.GroupTitle
|
||||
import com.anytypeio.anytype.presentation.objects.ObjectIcon
|
||||
import com.anytypeio.anytype.presentation.relations.getRelationFormat
|
||||
import com.anytypeio.anytype.presentation.search.ObjectSearchConstants
|
||||
import java.time.Instant
|
||||
import java.time.LocalDate
|
||||
|
@ -54,7 +60,7 @@ class VersionHistoryViewModel(
|
|||
private val _previewViewState =
|
||||
MutableStateFlow<VersionHistoryPreviewScreen>(VersionHistoryPreviewScreen.Hidden)
|
||||
val previewViewState = _previewViewState
|
||||
val navigation = MutableSharedFlow<VersionGroupNavigation>(0)
|
||||
val navigation = MutableSharedFlow<Command>(0)
|
||||
|
||||
init {
|
||||
Timber.d("VersionHistoryViewModel created")
|
||||
|
@ -68,30 +74,82 @@ class VersionHistoryViewModel(
|
|||
fun onGroupItemClicked(item: VersionHistoryGroup.Item) {
|
||||
viewModelScope.launch {
|
||||
_previewViewState.value = VersionHistoryPreviewScreen.Loading
|
||||
navigation.emit(VersionGroupNavigation.VersionPreview)
|
||||
navigation.emit(Command.VersionPreview)
|
||||
proceedShowVersion(item = item)
|
||||
}
|
||||
}
|
||||
|
||||
fun proceedWithClick(click: ListenerType) {
|
||||
Timber.d("Click: $click")
|
||||
viewModelScope.launch {
|
||||
when (click) {
|
||||
is ListenerType.Relation.Featured -> {
|
||||
proceedWithRelationValueNavigation(
|
||||
relation = RelationKey(click.relation.key),
|
||||
relationFormat = click.relation.getRelationFormat()
|
||||
)
|
||||
}
|
||||
|
||||
is ListenerType.Relation.Related -> {
|
||||
if (click.value is BlockView.Relation.Related) {
|
||||
proceedWithRelationValueNavigation(
|
||||
relation = RelationKey(click.value.view.key),
|
||||
relationFormat = click.value.view.getRelationFormat()
|
||||
)
|
||||
}
|
||||
}
|
||||
else -> {}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private suspend fun proceedWithRelationValueNavigation(
|
||||
relation: RelationKey,
|
||||
relationFormat: Relation.Format
|
||||
) {
|
||||
val currentState = (_previewViewState.value as? VersionHistoryPreviewScreen.Success) ?: return
|
||||
val isSet = currentState.isSet
|
||||
when (relationFormat) {
|
||||
RelationFormat.SHORT_TEXT,
|
||||
RelationFormat.LONG_TEXT,
|
||||
RelationFormat.URL,
|
||||
RelationFormat.PHONE,
|
||||
RelationFormat.NUMBER,
|
||||
RelationFormat.EMAIL -> navigation.emit(Command.RelationText(relation, isSet))
|
||||
|
||||
RelationFormat.DATE -> navigation.emit(Command.RelationDate(relation, isSet))
|
||||
Relation.Format.TAG,
|
||||
Relation.Format.STATUS -> navigation.emit(Command.RelationMultiSelect(relation, isSet))
|
||||
|
||||
Relation.Format.OBJECT,
|
||||
Relation.Format.FILE -> navigation.emit(Command.RelationObject(relation, isSet))
|
||||
|
||||
else -> {
|
||||
Timber.d("No interaction allowed with this relation with format:$relationFormat")
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
fun proceedWithHidePreview() {
|
||||
_previewViewState.value = VersionHistoryPreviewScreen.Hidden
|
||||
viewModelScope.launch {
|
||||
navigation.emit(VersionGroupNavigation.Main)
|
||||
navigation.emit(Command.Main)
|
||||
}
|
||||
}
|
||||
|
||||
fun proceedWithRestore() {
|
||||
val currentVersionId = (_previewViewState.value as? VersionHistoryPreviewScreen.Success)?.versionId ?: return
|
||||
val currentVersionId =
|
||||
(_previewViewState.value as? VersionHistoryPreviewScreen.Success)?.versionId ?: return
|
||||
viewModelScope.launch {
|
||||
val params = SetVersion.Params(
|
||||
objectId = vmParams.objectId,
|
||||
versionId = currentVersionId
|
||||
)
|
||||
objectId = vmParams.objectId,
|
||||
versionId = currentVersionId
|
||||
)
|
||||
setVersion.async(params).fold(
|
||||
onSuccess = {
|
||||
Timber.d("Version restored")
|
||||
_previewViewState.value = VersionHistoryPreviewScreen.Hidden
|
||||
navigation.emit(VersionGroupNavigation.ExitToObject)
|
||||
navigation.emit(Command.ExitToObject)
|
||||
},
|
||||
onFailure = {
|
||||
Timber.e(it, "Error while restoring version")
|
||||
|
@ -265,9 +323,11 @@ class VersionHistoryViewModel(
|
|||
currentDate -> {
|
||||
GroupTitle.Today
|
||||
}
|
||||
|
||||
currentDate.minusDays(1) -> {
|
||||
GroupTitle.Yesterday
|
||||
}
|
||||
|
||||
else -> {
|
||||
val pattern = if (givenYear == currentYear) {
|
||||
GROUP_DATE_FORMAT_CURRENT_YEAR
|
||||
|
@ -342,6 +402,7 @@ class VersionHistoryViewModel(
|
|||
val event = payload.events
|
||||
.filterIsInstance<Event.Command.ShowObject>()
|
||||
.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,
|
||||
|
@ -361,7 +422,8 @@ class VersionHistoryViewModel(
|
|||
blocks = blocks,
|
||||
dateFormatted = item.dateFormatted,
|
||||
timeFormatted = item.timeFormatted,
|
||||
icon = item.icon
|
||||
icon = item.icon,
|
||||
isSet = obj.layout.isDataView()
|
||||
)
|
||||
}
|
||||
}
|
||||
|
@ -374,8 +436,14 @@ class VersionHistoryViewModel(
|
|||
val spaceId: SpaceId
|
||||
)
|
||||
|
||||
sealed class Command {
|
||||
data class OpenVersion(val versionId: Id) : Command()
|
||||
sealed class Command(val route: String) {
|
||||
data object Main : Command("main")
|
||||
data object VersionPreview : Command("version preview")
|
||||
data object ExitToObject : Command("")
|
||||
data class RelationMultiSelect(val relationKey: RelationKey, val isSet: Boolean) : Command("relation_select")
|
||||
data class RelationObject(val relationKey: RelationKey, val isSet: Boolean) : Command("relation_object")
|
||||
data class RelationDate(val relationKey: RelationKey, val isSet: Boolean) : Command("relation_date")
|
||||
data class RelationText(val relationKey: RelationKey, val isSet: Boolean) : Command("relation_text")
|
||||
}
|
||||
|
||||
companion object {
|
||||
|
@ -403,7 +471,8 @@ sealed class VersionHistoryPreviewScreen {
|
|||
val blocks: List<BlockView>,
|
||||
val dateFormatted: String,
|
||||
val timeFormatted: String,
|
||||
val icon: ObjectIcon?
|
||||
val icon: ObjectIcon?,
|
||||
val isSet: Boolean
|
||||
) :
|
||||
VersionHistoryPreviewScreen()
|
||||
|
||||
|
@ -433,10 +502,4 @@ data class VersionHistoryGroup(
|
|||
data object Yesterday : GroupTitle()
|
||||
data class Date(val date: String) : GroupTitle()
|
||||
}
|
||||
}
|
||||
|
||||
sealed class VersionGroupNavigation(val route: String) {
|
||||
data object Main : VersionGroupNavigation("main")
|
||||
data object VersionPreview : VersionGroupNavigation("version preview")
|
||||
data object ExitToObject : VersionGroupNavigation("")
|
||||
}
|
|
@ -281,4 +281,18 @@ suspend fun getNotIncludedRecommendedRelations(
|
|||
val relationLinkKeys = relationLinks.map { it.key }.toSet()
|
||||
return storeOfRelations.getById(recommendedRelations)
|
||||
.filterNot { recommended -> recommended.key in relationLinkKeys }
|
||||
}
|
||||
|
||||
fun ObjectRelationView.getRelationFormat(): RelationFormat = when (this) {
|
||||
is ObjectRelationView.Object -> RelationFormat.OBJECT
|
||||
is ObjectRelationView.File -> RelationFormat.FILE
|
||||
is ObjectRelationView.Default -> format
|
||||
is ObjectRelationView.Status -> RelationFormat.STATUS
|
||||
is ObjectRelationView.Tags -> RelationFormat.TAG
|
||||
is ObjectRelationView.Checkbox -> RelationFormat.CHECKBOX
|
||||
is ObjectRelationView.Links.Backlinks -> RelationFormat.OBJECT
|
||||
is ObjectRelationView.Links.From -> RelationFormat.OBJECT
|
||||
is ObjectRelationView.ObjectType.Base -> RelationFormat.OBJECT
|
||||
is ObjectRelationView.ObjectType.Deleted -> RelationFormat.OBJECT
|
||||
is ObjectRelationView.Source -> RelationFormat.OBJECT
|
||||
}
|
Loading…
Add table
Add a link
Reference in a new issue