1
0
Fork 0
mirror of https://github.com/anyproto/anytype-kotlin.git synced 2025-06-07 21:37:02 +09:00

DROID-3564 App | Tech | DND improvements + remove legacy - Part 2 (#2304)

This commit is contained in:
Evgenii Kozlov 2025-04-13 21:24:13 +02:00 committed by GitHub
parent 900597c6a9
commit 65487ddcfe
Signed by: github
GPG key ID: B5690EEEBB952194
9 changed files with 108 additions and 101 deletions

View file

@ -226,7 +226,6 @@ dependencies {
implementation libs.composeAccompanistNavigation
implementation libs.preference
implementation libs.activityCompose
implementation libs.composeReorderableLegacy
implementation libs.composeReorderable
implementation libs.room

View file

@ -1,6 +1,5 @@
package com.anytypeio.anytype.ui.home
import android.view.View
import androidx.activity.compose.BackHandler
import androidx.compose.animation.AnimatedVisibility
import androidx.compose.animation.animateContentSize
@ -25,7 +24,6 @@ import androidx.compose.foundation.layout.height
import androidx.compose.foundation.layout.padding
import androidx.compose.foundation.layout.width
import androidx.compose.foundation.lazy.LazyColumn
import androidx.compose.foundation.lazy.LazyListState
import androidx.compose.foundation.lazy.itemsIndexed
import androidx.compose.foundation.lazy.rememberLazyListState
import androidx.compose.foundation.shape.RoundedCornerShape
@ -51,6 +49,7 @@ import com.anytypeio.anytype.core_ui.extensions.throttledClick
import com.anytypeio.anytype.core_ui.foundation.components.BottomNavigationMenu
import com.anytypeio.anytype.core_ui.foundation.noRippleClickable
import com.anytypeio.anytype.core_ui.views.UXBody
import com.anytypeio.anytype.core_ui.widgets.dv.DefaultDragAndDropModifier
import com.anytypeio.anytype.presentation.home.InteractionMode
import com.anytypeio.anytype.presentation.navigation.NavPanelState
import com.anytypeio.anytype.presentation.widgets.DropDownMenuAction
@ -72,11 +71,8 @@ import com.anytypeio.anytype.ui.widgets.types.ListWidgetCard
import com.anytypeio.anytype.ui.widgets.types.SpaceChatWidgetCard
import com.anytypeio.anytype.ui.widgets.types.SpaceWidgetCard
import com.anytypeio.anytype.ui.widgets.types.TreeWidgetCard
import sh.calvin.reorderable.ReorderableCollectionItemScope
import sh.calvin.reorderable.ReorderableItem
import sh.calvin.reorderable.ReorderableLazyListState
import sh.calvin.reorderable.rememberReorderableLazyListState
import timber.log.Timber
@Composable
fun HomeScreen(
@ -559,28 +555,6 @@ private fun WidgetList(
}
}
@Composable
private fun ReorderableCollectionItemScope.DefaultDragAndDropModifier(
view: View,
onDragStopped: () -> Unit
): Modifier {
return Modifier.draggableHandle(
onDragStarted = {
ViewCompat.performHapticFeedback(
view,
HapticFeedbackConstantsCompat.GESTURE_START
)
},
onDragStopped = {
ViewCompat.performHapticFeedback(
view,
HapticFeedbackConstantsCompat.GESTURE_END
)
onDragStopped()
}
)
}
@Composable
private fun ListOfObjectsItem(
modifier: Modifier = Modifier,

View file

@ -28,7 +28,6 @@ import androidx.compose.foundation.layout.PaddingValues
import androidx.compose.foundation.layout.Row
import androidx.compose.foundation.layout.WindowInsets
import androidx.compose.foundation.layout.absolutePadding
import androidx.compose.foundation.layout.fillMaxHeight
import androidx.compose.foundation.layout.fillMaxSize
import androidx.compose.foundation.layout.fillMaxWidth
import androidx.compose.foundation.layout.height
@ -40,6 +39,7 @@ import androidx.compose.foundation.layout.windowInsetsPadding
import androidx.compose.foundation.layout.wrapContentHeight
import androidx.compose.foundation.lazy.LazyColumn
import androidx.compose.foundation.lazy.items
import androidx.compose.foundation.lazy.rememberLazyListState
import androidx.compose.material.BottomSheetScaffold
import androidx.compose.material.BottomSheetValue
import androidx.compose.material.Divider
@ -76,6 +76,8 @@ import androidx.compose.ui.text.style.TextOverflow
import androidx.compose.ui.unit.Density
import androidx.compose.ui.unit.dp
import androidx.compose.ui.viewinterop.AndroidView
import androidx.core.view.HapticFeedbackConstantsCompat
import androidx.core.view.ViewCompat
import androidx.core.widget.doAfterTextChanged
import androidx.lifecycle.compose.collectAsStateWithLifecycle
import com.anytypeio.anytype.BuildConfig
@ -90,6 +92,7 @@ import com.anytypeio.anytype.core_ui.views.Title1
import com.anytypeio.anytype.core_ui.views.UXBody
import com.anytypeio.anytype.core_ui.widgets.CollectionActionWidget
import com.anytypeio.anytype.core_ui.widgets.ListWidgetObjectIcon
import com.anytypeio.anytype.core_ui.widgets.dv.DefaultDragAndDropModifier
import com.anytypeio.anytype.core_utils.ext.invisible
import com.anytypeio.anytype.core_utils.ext.setVisible
import com.anytypeio.anytype.core_utils.ext.visible
@ -108,10 +111,8 @@ import kotlinx.coroutines.flow.collectLatest
import kotlinx.coroutines.flow.distinctUntilChanged
import kotlinx.coroutines.flow.drop
import kotlinx.coroutines.launch
import org.burnoutcrew.reorderable.ReorderableItem
import org.burnoutcrew.reorderable.detectReorderAfterLongPress
import org.burnoutcrew.reorderable.rememberReorderableLazyListState
import org.burnoutcrew.reorderable.reorderable
import sh.calvin.reorderable.ReorderableItem
import sh.calvin.reorderable.rememberReorderableLazyListState
@SuppressLint("UnusedMaterialScaffoldPaddingParameter")
@Composable
@ -126,7 +127,7 @@ fun ScreenContent(
)
{
Box(
modifier = if (BuildConfig.USE_EDGE_TO_EDGE && Build.VERSION.SDK_INT >= EDGE_TO_EDGE_MIN_SDK)
modifier = if (Build.VERSION.SDK_INT >= EDGE_TO_EDGE_MIN_SDK)
Modifier.windowInsetsPadding(WindowInsets.systemBars)
else
Modifier
@ -210,34 +211,47 @@ fun ListView(
itemBackground: Color = colorResource(id = R.color.background_primary)
) {
val view = LocalView.current
val views = remember {
mutableStateOf<List<CollectionView>>(listOf())
}
val lazyListState = rememberReorderableLazyListState(
onMove = { from, to ->
val lazyListState = rememberLazyListState()
val lastFromIndex = remember { mutableStateOf<Int?>(null) }
val lastToIndex = remember { mutableStateOf<Int?>(null) }
val reorderableLazyListState = rememberReorderableLazyListState(lazyListState) { from, to ->
lastFromIndex.value = from.index
lastToIndex.value = to.index
views.value = views.value.toMutableList().apply {
add(to.index, removeAt(from.index))
}
},
onDragEnd = { from, to ->
ViewCompat.performHapticFeedback(
view,
HapticFeedbackConstantsCompat.SEGMENT_FREQUENT_TICK
)
}
val onDragStoppedHandler = {
val from = lastFromIndex.value
val to = lastToIndex.value
if (from != null && to != null && from != to) {
vm.onMove(views.value, from, to)
},
)
}
// Reset after firing
lastFromIndex.value = null
lastToIndex.value = null
}
uiState.views.fold(
onSuccess = { list ->
views.value = list
LazyColumn(
state = lazyListState.listState,
modifier = Modifier
.then(
if (uiState.inDragMode)
Modifier.reorderable(lazyListState)
else
Modifier
)
.fillMaxHeight()
.fillMaxWidth(),
state = lazyListState,
modifier = Modifier.fillMaxSize(),
contentPadding = PaddingValues(bottom = 180.dp)
) {
items(
@ -256,18 +270,13 @@ fun ListView(
when (item) {
is CollectionObjectView -> {
if (uiState.inDragMode) {
ReorderableItem(
lazyListState,
key = item.obj.id,
) { isDragging ->
ReorderableItem(reorderableLazyListState, key = item.obj.id,) { isDragging ->
val alpha = animateFloatAsState(if (isDragging) 0.8f else 1.0f)
Column(
modifier = Modifier
.then(
if (uiState.inDragMode) {
Modifier.detectReorderAfterLongPress(
lazyListState
)
DefaultDragAndDropModifier(view, onDragStoppedHandler)
} else {
Modifier
}
@ -303,7 +312,7 @@ fun ListView(
is SectionView -> {
if (uiState.inDragMode) {
ReorderableItem(
lazyListState,
reorderableLazyListState,
key = item.name,
) {
SectionItem(item)

View file

@ -1,7 +1,6 @@
package com.anytypeio.anytype.ui.widgets.types
import androidx.compose.animation.AnimatedVisibility
import androidx.compose.animation.animateContentSize
import androidx.compose.animation.fadeIn
import androidx.compose.animation.fadeOut
import androidx.compose.animation.slideInHorizontally
@ -15,7 +14,6 @@ import androidx.compose.foundation.layout.fillMaxWidth
import androidx.compose.foundation.layout.height
import androidx.compose.foundation.layout.padding
import androidx.compose.foundation.layout.width
import androidx.compose.foundation.lazy.LazyListState
import androidx.compose.foundation.lazy.rememberLazyListState
import androidx.compose.foundation.shape.RoundedCornerShape
import androidx.compose.material.Text
@ -40,9 +38,6 @@ import com.anytypeio.anytype.core_ui.views.HeadlineSubheading
import com.anytypeio.anytype.presentation.home.InteractionMode
import com.anytypeio.anytype.presentation.widgets.DropDownMenuAction
import com.anytypeio.anytype.ui.widgets.menu.WidgetMenu
import org.burnoutcrew.reorderable.ReorderableLazyListState
import org.burnoutcrew.reorderable.detectReorderAfterLongPress
import org.burnoutcrew.reorderable.rememberReorderableLazyListState
@OptIn(ExperimentalFoundationApi::class)
@Composable
@ -86,7 +81,6 @@ fun AllContentWidgetCard(
}
)
} else {
// Modifier.detectReorderAfterLongPress(lazyListState)
Modifier
}
)
@ -142,7 +136,6 @@ fun AllContentWidgetCard(
@DefaultPreviews
@Composable
fun AllContentWidgetPreview() {
val lazyListState = rememberLazyListState()
AllContentWidgetCard(
index = 0,
onWidgetClicked = {},

View file

@ -58,7 +58,7 @@ dependencies {
implementation libs.coilCompose
implementation libs.coilNetwork
implementation libs.composeConstraintLayout
implementation libs.composeReorderableLegacy
implementation libs.composeReorderable
testImplementation libs.fragmentTesting
testImplementation project(':test:android-utils')

View file

@ -1,6 +1,7 @@
package com.anytypeio.anytype.core_ui.widgets.dv
import android.view.HapticFeedbackConstants
import android.view.View
import androidx.compose.animation.animateContentSize
import androidx.compose.animation.core.Spring
import androidx.compose.animation.core.animateFloatAsState
@ -18,6 +19,7 @@ import androidx.compose.foundation.layout.padding
import androidx.compose.foundation.layout.windowInsetsPadding
import androidx.compose.foundation.layout.wrapContentHeight
import androidx.compose.foundation.lazy.LazyColumn
import androidx.compose.foundation.lazy.rememberLazyListState
import androidx.compose.foundation.shape.RoundedCornerShape
import androidx.compose.material.ExperimentalMaterialApi
import androidx.compose.material.Text
@ -26,6 +28,7 @@ import androidx.compose.material3.ModalBottomSheet
import androidx.compose.material3.rememberModalBottomSheetState
import androidx.compose.runtime.Composable
import androidx.compose.runtime.mutableStateListOf
import androidx.compose.runtime.mutableStateOf
import androidx.compose.runtime.remember
import androidx.compose.ui.Alignment
import androidx.compose.ui.Modifier
@ -40,6 +43,8 @@ import androidx.compose.ui.unit.dp
import androidx.constraintlayout.compose.ConstraintLayout
import androidx.constraintlayout.compose.Dimension
import androidx.constraintlayout.compose.Visibility
import androidx.core.view.HapticFeedbackConstantsCompat
import androidx.core.view.ViewCompat
import com.anytypeio.anytype.core_ui.R
import com.anytypeio.anytype.core_ui.extensions.swapList
import com.anytypeio.anytype.core_ui.foundation.Divider
@ -56,11 +61,9 @@ import com.anytypeio.anytype.presentation.sets.ViewersWidgetUi.Action.DoneMode
import com.anytypeio.anytype.presentation.sets.ViewersWidgetUi.Action.Edit
import com.anytypeio.anytype.presentation.sets.ViewersWidgetUi.Action.EditMode
import com.anytypeio.anytype.presentation.sets.viewer.ViewerView
import org.burnoutcrew.reorderable.ReorderableItem
import org.burnoutcrew.reorderable.ReorderableLazyListState
import org.burnoutcrew.reorderable.detectReorder
import org.burnoutcrew.reorderable.rememberReorderableLazyListState
import org.burnoutcrew.reorderable.reorderable
import sh.calvin.reorderable.ReorderableCollectionItemScope
import sh.calvin.reorderable.ReorderableItem
import sh.calvin.reorderable.rememberReorderableLazyListState
@OptIn(ExperimentalMaterialApi::class, ExperimentalMaterial3Api::class)
@ -114,17 +117,19 @@ private fun ViewersWidgetContent(
action: (ViewersWidgetUi.Action) -> Unit
) {
val view = LocalView.current
val lastFromIndex = remember { mutableStateOf<Int?>(null) }
val lastToIndex = remember { mutableStateOf<Int?>(null) }
val lazyListState = rememberLazyListState()
val views = remember { mutableStateListOf<ViewerView>() }
views.swapList(state.items)
val lazyListState = rememberReorderableLazyListState(
onMove = { from, to ->
val newList = views.toMutableList().apply {
add(to.index, removeAt(from.index))
}
views.swapList(newList)
},
onDragEnd = { from, to ->
val onDragStoppedHandler = {
val from = lastFromIndex.value
val to = lastToIndex.value
if (from != null && to != null && from != to) {
action(
ViewersWidgetUi.Action.OnMove(
currentViews = views,
@ -133,7 +138,25 @@ private fun ViewersWidgetContent(
)
)
}
)
// Reset after firing
lastFromIndex.value = null
lastToIndex.value = null
}
val reorderableLazyListState = rememberReorderableLazyListState(lazyListState) { from, to ->
lastFromIndex.value = from.index
lastToIndex.value = to.index
val newList = views.toMutableList().apply {
add(to.index, removeAt(from.index))
}
views.swapList(newList)
ViewCompat.performHapticFeedback(
view,
HapticFeedbackConstantsCompat.SEGMENT_FREQUENT_TICK
)
}
Column(
modifier = modifier
@ -150,9 +173,8 @@ private fun ViewersWidgetContent(
)
LazyColumn(
state = lazyListState.listState,
state = lazyListState,
modifier = Modifier
.reorderable(lazyListState)
.fillMaxWidth()
.wrapContentHeight()
) {
@ -160,26 +182,20 @@ private fun ViewersWidgetContent(
count = views.size,
key = { index -> views[index].id },
) { index ->
ReorderableItem(
modifier = Modifier.animateItem(),
reorderableState = lazyListState,
key = views[index].id
) { isDragging ->
ReorderableItem(reorderableLazyListState, key = views[index].id) { isDragging ->
val currentItem = LocalView.current
if (isDragging) {
currentItem.isHapticFeedbackEnabled = true
currentItem.performHapticFeedback(HapticFeedbackConstants.LONG_PRESS)
}
Item(
dndModifier = DefaultDragAndDropModifier(view, onDragStoppedHandler),
modifier = Modifier,
lazyListState = lazyListState,
isDragging = isDragging,
isEditing = state.isEditing,
action = action,
view = views[index]
)
}
if (index != views.size - 1) {
Divider()
@ -191,8 +207,8 @@ private fun ViewersWidgetContent(
@Composable
private fun Item(
dndModifier: Modifier = Modifier,
modifier: Modifier,
lazyListState: ReorderableLazyListState,
isDragging: Boolean,
isEditing: Boolean,
action: (ViewersWidgetUi.Action) -> Unit,
@ -228,8 +244,7 @@ private fun Item(
contentDescription = "Delete view"
)
Image(
modifier = Modifier
.detectReorder(lazyListState)
modifier = dndModifier
.constrainAs(dnd) {
end.linkTo(parent.end)
top.linkTo(parent.top)
@ -386,4 +401,26 @@ private fun ActionText(modifier: Modifier, text: String, click: () -> Unit) {
color = colorResource(id = R.color.glyph_active),
textAlign = TextAlign.Center
)
}
}
@Composable
fun ReorderableCollectionItemScope.DefaultDragAndDropModifier(
view: View,
onDragStopped: () -> Unit
): Modifier {
return Modifier.draggableHandle(
onDragStarted = {
ViewCompat.performHapticFeedback(
view,
HapticFeedbackConstantsCompat.GESTURE_START
)
},
onDragStopped = {
ViewCompat.performHapticFeedback(
view,
HapticFeedbackConstantsCompat.GESTURE_END
)
onDragStopped()
}
)
}

View file

@ -83,7 +83,6 @@ composeAccompanistPermissions = { module = "com.google.accompanist:accompanist-p
composeAccompanistPagerIndicators = { module = "com.google.accompanist:accompanist-pager-indicators", version.ref = "accompanistVersion" }
composeAccompanistThemeAdapter = { module = "com.google.accompanist:accompanist-themeadapter-material", version.ref = "accompanistVersion" }
composeAccompanistNavigation = { module = "com.google.accompanist:accompanist-navigation-material", version.ref = "accompanistVersion" }
composeReorderableLegacy = { module = "com.github.fat-fellow.ComposeReorderable:reorderable", version.ref = "composeReorderableLegacyVersion" }
composeReorderable = { module = "sh.calvin.reorderable:reorderable", version.ref = "composeReorderableVersion" }
composeConstraintLayout = { module = "androidx.constraintlayout:constraintlayout-compose", version.ref = "composeConstraintLayoutVersion" }
kotlinxSerializationJson = { module = "org.jetbrains.kotlinx:kotlinx-serialization-json", version = "1.6.3" }

View file

@ -2608,11 +2608,6 @@ class ObjectSetViewModel(
}
is ViewersWidgetUi.Action.OnMove -> {
if (action.from == action.to) return
if (action.to == 0 && session.currentViewerId.value.isNullOrEmpty()) {
state.dataViewContent.viewers.firstOrNull()?.let {
session.currentViewerId.value = it.id
}
}
viewModelScope.launch {
val startTime = System.currentTimeMillis()
val type = action.currentViews[action.to].type
@ -2634,6 +2629,7 @@ class ObjectSetViewModel(
}
)
)
session.currentViewerId.value = action.currentViews.firstOrNull()?.id
}
}
is ViewersWidgetUi.Action.SetActive -> {

View file

@ -65,7 +65,7 @@ dependencies {
implementation libs.composeAccompanistPagerIndicators
implementation libs.preference
implementation libs.activityCompose
implementation libs.composeReorderableLegacy
implementation libs.composeReorderable
debugImplementation libs.composeTooling
testImplementation libs.junit