mirror of
https://github.com/anyproto/anytype-kotlin.git
synced 2025-06-08 05:47:05 +09:00
DROID-2795 Date as an object | Move to bin by right-to-left swipe (#1883)
This commit is contained in:
parent
cc970f3a3f
commit
c0439ba497
11 changed files with 262 additions and 14 deletions
|
@ -18,6 +18,7 @@ import com.anytypeio.anytype.domain.misc.UrlBuilder
|
|||
import com.anytypeio.anytype.domain.multiplayer.UserPermissionProvider
|
||||
import com.anytypeio.anytype.domain.`object`.GetObject
|
||||
import com.anytypeio.anytype.domain.`object`.SetObjectDetails
|
||||
import com.anytypeio.anytype.domain.objects.SetObjectListIsArchived
|
||||
import com.anytypeio.anytype.domain.objects.StoreOfObjectTypes
|
||||
import com.anytypeio.anytype.domain.objects.StoreOfRelations
|
||||
import com.anytypeio.anytype.domain.page.CreateObject
|
||||
|
@ -135,6 +136,14 @@ object DateObjectModule {
|
|||
dispatchers: AppCoroutineDispatchers
|
||||
): SetObjectDetails = SetObjectDetails(repository, dispatchers)
|
||||
|
||||
@JvmStatic
|
||||
@PerScreen
|
||||
@Provides
|
||||
fun getSetObjectListIsArchived(
|
||||
repo: BlockRepository,
|
||||
dispatchers: AppCoroutineDispatchers
|
||||
): SetObjectListIsArchived = SetObjectListIsArchived(repo, dispatchers)
|
||||
|
||||
@Module
|
||||
interface Declarations {
|
||||
@PerScreen
|
||||
|
|
|
@ -154,6 +154,9 @@ class DateObjectFragment : BaseComposeFragment(), ObjectTypeSelectionListener {
|
|||
is DateObjectCommand.SendToast.UnexpectedLayout -> {
|
||||
toast("Unexpected layout")
|
||||
}
|
||||
is DateObjectCommand.SendToast.Error -> {
|
||||
toast(effect.message)
|
||||
}
|
||||
DateObjectCommand.TypeSelectionScreen -> {
|
||||
val dialog = ObjectTypeSelectionFragment.new(space = space)
|
||||
dialog.show(childFragmentManager, null)
|
||||
|
@ -198,6 +201,7 @@ class DateObjectFragment : BaseComposeFragment(), ObjectTypeSelectionListener {
|
|||
canPaginate = vm.canPaginate.collectAsStateWithLifecycle().value,
|
||||
uiCalendarState = vm.uiCalendarState.collectAsStateWithLifecycle().value,
|
||||
uiSyncStatusState = vm.uiSyncStatusWidgetState.collectAsStateWithLifecycle().value,
|
||||
uiSnackbarState = vm.uiSnackbarState.collectAsStateWithLifecycle().value,
|
||||
onDateEvent = vm::onDateEvent
|
||||
)
|
||||
}
|
||||
|
|
|
@ -57,7 +57,8 @@ fun ObjectWrapper.Basic.toUiObjectsListItem(
|
|||
space: SpaceId,
|
||||
urlBuilder: UrlBuilder,
|
||||
objectTypes: List<ObjectWrapper.Type>,
|
||||
fieldParser: FieldParser
|
||||
fieldParser: FieldParser,
|
||||
isOwnerOrEditor: Boolean
|
||||
): UiObjectsListItem {
|
||||
val obj = this
|
||||
val typeUrl = obj.getProperType()
|
||||
|
@ -76,6 +77,7 @@ fun ObjectWrapper.Basic.toUiObjectsListItem(
|
|||
}
|
||||
}?.name,
|
||||
layout = layout,
|
||||
icon = obj.objectIcon(builder = urlBuilder)
|
||||
icon = obj.objectIcon(builder = urlBuilder),
|
||||
isPossibleToDelete = isOwnerOrEditor
|
||||
)
|
||||
}
|
|
@ -14,15 +14,22 @@ import androidx.compose.foundation.layout.padding
|
|||
import androidx.compose.foundation.layout.statusBars
|
||||
import androidx.compose.foundation.layout.windowInsetsPadding
|
||||
import androidx.compose.foundation.layout.windowInsetsTopHeight
|
||||
import androidx.compose.foundation.layout.wrapContentHeight
|
||||
import androidx.compose.material3.ExperimentalMaterial3Api
|
||||
import androidx.compose.material3.Scaffold
|
||||
import androidx.compose.material3.SnackbarDuration
|
||||
import androidx.compose.material3.SnackbarHost
|
||||
import androidx.compose.material3.SnackbarHostState
|
||||
import androidx.compose.material3.SnackbarResult
|
||||
import androidx.compose.runtime.Composable
|
||||
import androidx.compose.runtime.LaunchedEffect
|
||||
import androidx.compose.runtime.remember
|
||||
import androidx.compose.runtime.rememberCoroutineScope
|
||||
import androidx.compose.ui.Alignment
|
||||
import androidx.compose.ui.Modifier
|
||||
import androidx.compose.ui.res.colorResource
|
||||
import androidx.compose.ui.res.stringResource
|
||||
import androidx.compose.ui.unit.dp
|
||||
import com.anytypeio.anytype.core_models.Id
|
||||
import com.anytypeio.anytype.core_ui.foundation.components.BottomNavigationMenu
|
||||
import com.anytypeio.anytype.core_ui.syncstatus.SpaceSyncStatusScreen
|
||||
import com.anytypeio.anytype.core_utils.insets.EDGE_TO_EDGE_MIN_SDK
|
||||
|
@ -36,8 +43,11 @@ import com.anytypeio.anytype.feature_date.viewmodel.UiFieldsState
|
|||
import com.anytypeio.anytype.feature_date.viewmodel.UiHeaderState
|
||||
import com.anytypeio.anytype.feature_date.viewmodel.UiNavigationWidget
|
||||
import com.anytypeio.anytype.feature_date.viewmodel.UiObjectsListState
|
||||
import com.anytypeio.anytype.feature_date.viewmodel.UiSnackbarState
|
||||
import com.anytypeio.anytype.feature_date.viewmodel.UiSyncStatusBadgeState
|
||||
import com.anytypeio.anytype.feature_date.viewmodel.UiSyncStatusWidgetState
|
||||
import kotlinx.coroutines.CoroutineScope
|
||||
import kotlinx.coroutines.launch
|
||||
|
||||
@OptIn(ExperimentalMaterial3Api::class)
|
||||
@Composable
|
||||
|
@ -52,12 +62,31 @@ fun DateMainScreen(
|
|||
uiSyncStatusState: UiSyncStatusWidgetState,
|
||||
uiCalendarState: UiCalendarState,
|
||||
uiContentState: UiContentState,
|
||||
uiSnackbarState: UiSnackbarState,
|
||||
canPaginate: Boolean,
|
||||
onDateEvent: (DateEvent) -> Unit
|
||||
) {
|
||||
|
||||
val scope = rememberCoroutineScope()
|
||||
|
||||
val snackBarHostState = remember { SnackbarHostState() }
|
||||
|
||||
val snackBarText = stringResource(R.string.all_content_snackbar_title)
|
||||
val undoText = stringResource(R.string.undo)
|
||||
|
||||
LaunchedEffect(key1 = uiSnackbarState) {
|
||||
if (uiSnackbarState is UiSnackbarState.Visible) {
|
||||
showMoveToBinSnackbar(
|
||||
message = "'${uiSnackbarState.message}' $snackBarText",
|
||||
undo = undoText,
|
||||
scope = this,
|
||||
snackBarHostState = snackBarHostState,
|
||||
objectId = uiSnackbarState.objId,
|
||||
onDateEvent = onDateEvent
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
Scaffold(
|
||||
modifier = Modifier.fillMaxSize(),
|
||||
containerColor = colorResource(id = R.color.background_primary),
|
||||
|
@ -152,6 +181,9 @@ fun DateMainScreen(
|
|||
isOwnerOrEditor = uiNavigationWidget is UiNavigationWidget.Editor
|
||||
)
|
||||
}
|
||||
},
|
||||
snackbarHost = {
|
||||
SnackbarHost(hostState = snackBarHostState)
|
||||
}
|
||||
)
|
||||
if (uiSyncStatusState is UiSyncStatusWidgetState.Visible) {
|
||||
|
@ -179,4 +211,32 @@ fun DateMainScreen(
|
|||
onDateEvent = onDateEvent
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
private fun showMoveToBinSnackbar(
|
||||
objectId: Id,
|
||||
message: String,
|
||||
undo: String,
|
||||
scope: CoroutineScope,
|
||||
snackBarHostState: SnackbarHostState,
|
||||
onDateEvent: (DateEvent) -> Unit
|
||||
) {
|
||||
scope.launch {
|
||||
val result = snackBarHostState
|
||||
.showSnackbar(
|
||||
message = message,
|
||||
actionLabel = undo,
|
||||
duration = SnackbarDuration.Short,
|
||||
withDismissAction = true
|
||||
)
|
||||
when (result) {
|
||||
SnackbarResult.ActionPerformed -> {
|
||||
onDateEvent(DateEvent.Snackbar.UndoMoveToBin(objectId))
|
||||
}
|
||||
|
||||
SnackbarResult.Dismissed -> {
|
||||
onDateEvent(DateEvent.Snackbar.OnSnackbarDismiss)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
|
@ -1,6 +1,10 @@
|
|||
package com.anytypeio.anytype.feature_date.ui
|
||||
|
||||
import androidx.compose.animation.AnimatedVisibility
|
||||
import androidx.compose.animation.core.animateFloatAsState
|
||||
import androidx.compose.animation.core.tween
|
||||
import androidx.compose.animation.fadeOut
|
||||
import androidx.compose.animation.shrinkVertically
|
||||
import androidx.compose.foundation.layout.Box
|
||||
import androidx.compose.foundation.layout.BoxScope
|
||||
import androidx.compose.foundation.layout.Row
|
||||
|
@ -16,6 +20,9 @@ import androidx.compose.foundation.lazy.rememberLazyListState
|
|||
import androidx.compose.material.Text
|
||||
import androidx.compose.material3.ListItem
|
||||
import androidx.compose.material3.ListItemDefaults
|
||||
import androidx.compose.material3.SwipeToDismissBox
|
||||
import androidx.compose.material3.SwipeToDismissBoxValue
|
||||
import androidx.compose.material3.rememberSwipeToDismissBoxState
|
||||
import androidx.compose.runtime.Composable
|
||||
import androidx.compose.runtime.LaunchedEffect
|
||||
import androidx.compose.runtime.derivedStateOf
|
||||
|
@ -24,6 +31,7 @@ import androidx.compose.runtime.mutableStateListOf
|
|||
import androidx.compose.runtime.mutableStateOf
|
||||
import androidx.compose.runtime.remember
|
||||
import androidx.compose.runtime.rememberCoroutineScope
|
||||
import androidx.compose.runtime.setValue
|
||||
import androidx.compose.ui.Alignment
|
||||
import androidx.compose.ui.Modifier
|
||||
import androidx.compose.ui.graphics.graphicsLayer
|
||||
|
@ -34,6 +42,8 @@ import androidx.compose.ui.unit.dp
|
|||
import com.anytypeio.anytype.core_ui.common.DefaultPreviews
|
||||
import com.anytypeio.anytype.core_ui.common.ShimmerEffect
|
||||
import com.anytypeio.anytype.core_ui.extensions.swapList
|
||||
import com.anytypeio.anytype.core_ui.foundation.DismissBackground
|
||||
import com.anytypeio.anytype.core_ui.foundation.Divider
|
||||
import com.anytypeio.anytype.core_ui.foundation.noRippleThrottledClickable
|
||||
import com.anytypeio.anytype.core_ui.views.ButtonSize
|
||||
import com.anytypeio.anytype.core_ui.views.PreviewTitle2Regular
|
||||
|
@ -47,6 +57,7 @@ import com.anytypeio.anytype.feature_date.ui.models.StubVerticalItems
|
|||
import com.anytypeio.anytype.feature_date.viewmodel.UiContentState
|
||||
import com.anytypeio.anytype.feature_date.viewmodel.UiObjectsListItem
|
||||
import com.anytypeio.anytype.feature_date.viewmodel.UiObjectsListState
|
||||
import kotlinx.coroutines.delay
|
||||
import kotlinx.coroutines.launch
|
||||
|
||||
@Composable
|
||||
|
@ -100,15 +111,18 @@ fun ObjectsScreen(
|
|||
val item = items[index]
|
||||
when (item) {
|
||||
is UiObjectsListItem.Item -> {
|
||||
ListItem(
|
||||
SwipeToDismissListItems(
|
||||
modifier = Modifier
|
||||
.fillMaxWidth()
|
||||
.animateItem()
|
||||
.noRippleThrottledClickable {
|
||||
onDateEvent(DateEvent.ObjectsList.OnObjectClicked(item))
|
||||
},
|
||||
item = item
|
||||
item = item,
|
||||
onDateEvent = onDateEvent
|
||||
)
|
||||
Divider(paddingStart = 16.dp, paddingEnd = 16.dp)
|
||||
}
|
||||
|
||||
is UiObjectsListItem.Loading -> {
|
||||
ListItemLoading(modifier = Modifier)
|
||||
}
|
||||
|
@ -229,6 +243,71 @@ private fun ListItemLoading(
|
|||
)
|
||||
}
|
||||
|
||||
@Composable
|
||||
fun SwipeToDismissListItems(
|
||||
item: UiObjectsListItem.Item,
|
||||
modifier: Modifier,
|
||||
animationDuration: Int = 500,
|
||||
onDateEvent: (DateEvent) -> Unit,
|
||||
) {
|
||||
var isRemoved by remember { mutableStateOf(false) }
|
||||
val dismissState = rememberSwipeToDismissBoxState(
|
||||
initialValue = SwipeToDismissBoxValue.Settled,
|
||||
confirmValueChange = { value ->
|
||||
if (value == SwipeToDismissBoxValue.EndToStart) {
|
||||
isRemoved = true
|
||||
true
|
||||
} else {
|
||||
false
|
||||
}
|
||||
return@rememberSwipeToDismissBoxState true
|
||||
},
|
||||
positionalThreshold = { it * .5f }
|
||||
)
|
||||
|
||||
if (dismissState.currentValue != SwipeToDismissBoxValue.Settled) {
|
||||
LaunchedEffect(Unit) {
|
||||
dismissState.snapTo(SwipeToDismissBoxValue.Settled)
|
||||
}
|
||||
}
|
||||
|
||||
LaunchedEffect(key1 = isRemoved) {
|
||||
if (isRemoved) {
|
||||
delay(animationDuration.toLong())
|
||||
onDateEvent(DateEvent.ObjectsList.OnObjectMoveToBin(item))
|
||||
}
|
||||
}
|
||||
AnimatedVisibility(
|
||||
visible = !isRemoved,
|
||||
exit = shrinkVertically(
|
||||
animationSpec = tween(durationMillis = animationDuration),
|
||||
shrinkTowards = Alignment.Top
|
||||
) + fadeOut()
|
||||
) {
|
||||
SwipeToDismissBox(
|
||||
modifier = modifier,
|
||||
state = dismissState,
|
||||
enableDismissFromEndToStart = item.isPossibleToDelete,
|
||||
enableDismissFromStartToEnd = false,
|
||||
backgroundContent = {
|
||||
DismissBackground(
|
||||
actionText = stringResource(R.string.move_to_bin),
|
||||
dismissState = dismissState
|
||||
)
|
||||
},
|
||||
content = {
|
||||
ListItem(
|
||||
modifier = Modifier
|
||||
.noRippleThrottledClickable {
|
||||
onDateEvent(DateEvent.ObjectsList.OnObjectClicked(item))
|
||||
},
|
||||
item = item
|
||||
)
|
||||
}
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
@Composable
|
||||
private fun BoxScope.LoadingState() {
|
||||
val loadingAlpha by animateFloatAsState(targetValue = 1f, label = "")
|
||||
|
|
|
@ -42,6 +42,7 @@ sealed class DateEvent {
|
|||
|
||||
sealed class ObjectsList : DateEvent() {
|
||||
data class OnObjectClicked(val item: UiObjectsListItem) : ObjectsList()
|
||||
data class OnObjectMoveToBin(val item: UiObjectsListItem.Item) : ObjectsList()
|
||||
data object OnLoadMore : ObjectsList()
|
||||
}
|
||||
|
||||
|
@ -53,4 +54,9 @@ sealed class DateEvent {
|
|||
sealed class SyncStatusWidget : DateEvent() {
|
||||
data object OnSyncStatusDismiss : SyncStatusWidget()
|
||||
}
|
||||
|
||||
sealed class Snackbar : DateEvent() {
|
||||
data object OnSnackbarDismiss : Snackbar()
|
||||
data class UndoMoveToBin(val objectId: String) : Snackbar()
|
||||
}
|
||||
}
|
|
@ -137,7 +137,8 @@ sealed class UiObjectsListItem {
|
|||
val typeName: String? = null,
|
||||
val createdBy: String? = null,
|
||||
val layout: ObjectType.Layout? = null,
|
||||
val icon: ObjectIcon = ObjectIcon.None
|
||||
val icon: ObjectIcon = ObjectIcon.None,
|
||||
val isPossibleToDelete: Boolean = false
|
||||
) : UiObjectsListItem()
|
||||
}
|
||||
|
||||
|
@ -179,3 +180,8 @@ sealed class UiErrorState {
|
|||
data class Other(val msg: String) : Reason()
|
||||
}
|
||||
}
|
||||
|
||||
sealed class UiSnackbarState {
|
||||
data object Hidden : UiSnackbarState()
|
||||
data class Visible(val message: String, val objId: Id) : UiSnackbarState()
|
||||
}
|
||||
|
|
|
@ -11,6 +11,7 @@ sealed class DateObjectCommand {
|
|||
data object TypeSelectionScreen : DateObjectCommand()
|
||||
data object ExitToSpaceWidgets : DateObjectCommand()
|
||||
sealed class SendToast : DateObjectCommand() {
|
||||
data class Error(val message: String) : SendToast()
|
||||
data class UnexpectedLayout(val layout: String) : SendToast()
|
||||
}
|
||||
data object OpenGlobalSearch : DateObjectCommand()
|
||||
|
|
|
@ -9,6 +9,7 @@ import com.anytypeio.anytype.domain.misc.DateProvider
|
|||
import com.anytypeio.anytype.domain.misc.UrlBuilder
|
||||
import com.anytypeio.anytype.domain.multiplayer.UserPermissionProvider
|
||||
import com.anytypeio.anytype.domain.`object`.GetObject
|
||||
import com.anytypeio.anytype.domain.objects.SetObjectListIsArchived
|
||||
import com.anytypeio.anytype.domain.objects.StoreOfObjectTypes
|
||||
import com.anytypeio.anytype.domain.objects.StoreOfRelations
|
||||
import com.anytypeio.anytype.domain.page.CreateObject
|
||||
|
@ -31,7 +32,8 @@ class DateObjectVMFactory @Inject constructor(
|
|||
private val dateProvider: DateProvider,
|
||||
private val spaceSyncAndP2PStatusProvider: SpaceSyncAndP2PStatusProvider,
|
||||
private val createObject: CreateObject,
|
||||
private val fieldParser: FieldParser
|
||||
private val fieldParser: FieldParser,
|
||||
private val setObjectListIsArchived: SetObjectListIsArchived
|
||||
) : ViewModelProvider.Factory {
|
||||
|
||||
@Suppress("UNCHECKED_CAST")
|
||||
|
@ -50,6 +52,8 @@ class DateObjectVMFactory @Inject constructor(
|
|||
dateProvider = dateProvider,
|
||||
spaceSyncAndP2PStatusProvider = spaceSyncAndP2PStatusProvider,
|
||||
createObject = createObject,
|
||||
fieldParser = fieldParser
|
||||
fieldParser = fieldParser,
|
||||
setObjectListIsArchived = setObjectListIsArchived
|
||||
|
||||
) as T
|
||||
}
|
|
@ -21,6 +21,7 @@ import com.anytypeio.anytype.domain.misc.DateProvider
|
|||
import com.anytypeio.anytype.domain.misc.UrlBuilder
|
||||
import com.anytypeio.anytype.domain.multiplayer.UserPermissionProvider
|
||||
import com.anytypeio.anytype.domain.`object`.GetObject
|
||||
import com.anytypeio.anytype.domain.objects.SetObjectListIsArchived
|
||||
import com.anytypeio.anytype.domain.objects.StoreOfObjectTypes
|
||||
import com.anytypeio.anytype.domain.objects.StoreOfRelations
|
||||
import com.anytypeio.anytype.domain.page.CreateObject
|
||||
|
@ -41,6 +42,7 @@ import com.anytypeio.anytype.presentation.search.GlobalSearchViewModel.Companion
|
|||
import com.anytypeio.anytype.presentation.search.ObjectSearchConstants.defaultKeys
|
||||
import com.anytypeio.anytype.presentation.sync.toSyncStatusWidgetState
|
||||
import kotlin.collections.map
|
||||
import kotlin.text.take
|
||||
import kotlinx.coroutines.ExperimentalCoroutinesApi
|
||||
import kotlinx.coroutines.FlowPreview
|
||||
import kotlinx.coroutines.flow.Flow
|
||||
|
@ -82,7 +84,8 @@ class DateObjectViewModel(
|
|||
private val dateProvider: DateProvider,
|
||||
private val spaceSyncAndP2PStatusProvider: SpaceSyncAndP2PStatusProvider,
|
||||
private val createObject: CreateObject,
|
||||
private val fieldParser: FieldParser
|
||||
private val fieldParser: FieldParser,
|
||||
private val setObjectListIsArchived: SetObjectListIsArchived
|
||||
) : ViewModel(), AnalyticSpaceHelperDelegate by analyticSpaceHelperDelegate {
|
||||
|
||||
val uiCalendarIconState = MutableStateFlow<UiCalendarIconState>(UiCalendarIconState.Hidden)
|
||||
|
@ -97,6 +100,7 @@ class DateObjectViewModel(
|
|||
val uiCalendarState = MutableStateFlow<UiCalendarState>(UiCalendarState.Hidden)
|
||||
val uiSyncStatusWidgetState =
|
||||
MutableStateFlow<UiSyncStatusWidgetState>(UiSyncStatusWidgetState.Hidden)
|
||||
val uiSnackbarState = MutableStateFlow<UiSnackbarState>(UiSnackbarState.Hidden)
|
||||
|
||||
val effects = MutableSharedFlow<DateObjectCommand>()
|
||||
val errorState = MutableStateFlow<UiErrorState>(UiErrorState.Hidden)
|
||||
|
@ -397,7 +401,8 @@ class DateObjectViewModel(
|
|||
space = vmParams.spaceId,
|
||||
urlBuilder = urlBuilder,
|
||||
objectTypes = storeOfObjectTypes.getAll(),
|
||||
fieldParser = fieldParser
|
||||
fieldParser = fieldParser,
|
||||
isOwnerOrEditor = permission.value?.isOwnerOrEditor() == true
|
||||
)
|
||||
}
|
||||
uiContentState.value = if (items.isEmpty()) {
|
||||
|
@ -640,6 +645,18 @@ class DateObjectViewModel(
|
|||
is DateEvent.NavigationWidget -> onNavigationWidgetEvent(event)
|
||||
is DateEvent.ObjectsList -> onObjectsListEvent(event)
|
||||
is DateEvent.SyncStatusWidget -> onSyncStatusWidgetEvent(event)
|
||||
is DateEvent.Snackbar -> onSnackbarEvent(event)
|
||||
}
|
||||
}
|
||||
|
||||
private fun onSnackbarEvent(event: DateEvent.Snackbar) {
|
||||
when (event) {
|
||||
DateEvent.Snackbar.OnSnackbarDismiss -> {
|
||||
proceedWithDismissSnackbar()
|
||||
}
|
||||
is DateEvent.Snackbar.UndoMoveToBin -> {
|
||||
proceedWithUndoMoveToBin(event.objectId)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -666,6 +683,7 @@ class DateObjectViewModel(
|
|||
when (event) {
|
||||
DateEvent.ObjectsList.OnLoadMore -> updateLimit()
|
||||
is DateEvent.ObjectsList.OnObjectClicked -> onItemClicked(event.item)
|
||||
is DateEvent.ObjectsList.OnObjectMoveToBin -> proceedWithMoveToBin(event.item)
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -797,6 +815,48 @@ class DateObjectViewModel(
|
|||
}
|
||||
}
|
||||
}
|
||||
|
||||
fun proceedWithMoveToBin(item: UiObjectsListItem.Item) {
|
||||
val params = SetObjectListIsArchived.Params(
|
||||
targets = listOf(item.id),
|
||||
isArchived = true
|
||||
)
|
||||
viewModelScope.launch {
|
||||
setObjectListIsArchived.async(params).fold(
|
||||
onSuccess = { ids ->
|
||||
Timber.d("Successfully archived object: $ids")
|
||||
val name = item.name
|
||||
uiSnackbarState.value = UiSnackbarState.Visible(
|
||||
message = name.take(10),
|
||||
objId = item.id
|
||||
)
|
||||
},
|
||||
onFailure = { e ->
|
||||
Timber.e(e, "Error while archiving object")
|
||||
effects.emit(DateObjectCommand.SendToast.Error("Error while archiving object"))
|
||||
}
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
fun proceedWithUndoMoveToBin(objectId: Id) {
|
||||
val params = SetObjectListIsArchived.Params(
|
||||
targets = listOf(objectId),
|
||||
isArchived = false
|
||||
)
|
||||
viewModelScope.launch {
|
||||
setObjectListIsArchived.async(params).fold(
|
||||
onSuccess = { ids ->
|
||||
Timber.d("Successfully archived object: $ids")
|
||||
uiSnackbarState.value = UiSnackbarState.Hidden
|
||||
},
|
||||
onFailure = { e ->
|
||||
Timber.e(e, "Error while un-archiving object")
|
||||
effects.emit(DateObjectCommand.SendToast.Error("Error while un-archiving object"))
|
||||
}
|
||||
)
|
||||
}
|
||||
}
|
||||
//endregion
|
||||
|
||||
//region Ui State
|
||||
|
@ -847,6 +907,10 @@ class DateObjectViewModel(
|
|||
)
|
||||
}
|
||||
}
|
||||
|
||||
fun proceedWithDismissSnackbar() {
|
||||
uiSnackbarState.value = UiSnackbarState.Hidden
|
||||
}
|
||||
//endregion
|
||||
|
||||
companion object {
|
||||
|
|
|
@ -656,9 +656,22 @@ class CollectionViewModel(
|
|||
}
|
||||
|
||||
private fun changeObjectListBinStatus(ids: List<Id>, isArchived: Boolean) {
|
||||
launch {
|
||||
setObjectListIsArchived.stream(SetObjectListIsArchived.Params(ids, isArchived))
|
||||
.collect { it.progressiveFold() }
|
||||
viewModelScope.launch {
|
||||
val params = SetObjectListIsArchived.Params(ids, isArchived)
|
||||
setObjectListIsArchived.async(params)
|
||||
.fold(
|
||||
onSuccess = {
|
||||
if (isArchived) {
|
||||
toasts.emit("Objects moved to bin")
|
||||
} else {
|
||||
toasts.emit("Objects restored")
|
||||
}
|
||||
},
|
||||
onFailure = {
|
||||
toasts.emit("Error while moving files to bin")
|
||||
Timber.e(it, "Error while moving files to bin")
|
||||
}
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue