From 5dad21f4eae870ed417344ca4f0dfcd130636512 Mon Sep 17 00:00:00 2001 From: FooIbar <118464521+FooIbar@users.noreply.github.com> Date: Sun, 26 Nov 2023 21:40:34 +0800 Subject: [PATCH] Fix download label drag and drop --- .../ehviewer/ui/scene/DownloadsFragment.kt | 105 +++++++------- .../ehviewer/ui/scene/GalleryListFragment.kt | 136 +++++++++--------- .../ehviewer/ui/scene/HistoryFragment.kt | 48 +++---- .../ehviewer/ui/tools/SwipeToDismissBox2.kt | 37 +++++ 4 files changed, 174 insertions(+), 152 deletions(-) create mode 100644 app/src/main/kotlin/com/hippo/ehviewer/ui/tools/SwipeToDismissBox2.kt diff --git a/app/src/main/kotlin/com/hippo/ehviewer/ui/scene/DownloadsFragment.kt b/app/src/main/kotlin/com/hippo/ehviewer/ui/scene/DownloadsFragment.kt index b5c549941..79060ef0b 100644 --- a/app/src/main/kotlin/com/hippo/ehviewer/ui/scene/DownloadsFragment.kt +++ b/app/src/main/kotlin/com/hippo/ehviewer/ui/scene/DownloadsFragment.kt @@ -46,7 +46,6 @@ import androidx.compose.material3.Icon import androidx.compose.material3.IconButton import androidx.compose.material3.ListItem import androidx.compose.material3.MaterialTheme -import androidx.compose.material3.SwipeToDismissBox import androidx.compose.material3.Text import androidx.compose.material3.TopAppBar import androidx.compose.material3.rememberDismissState @@ -92,7 +91,7 @@ import com.hippo.ehviewer.ui.showMoveDownloadLabelList import com.hippo.ehviewer.ui.tools.Deferred import com.hippo.ehviewer.ui.tools.FastScrollLazyColumn import com.hippo.ehviewer.ui.tools.LocalDialogState -import com.hippo.ehviewer.ui.tools.LocalTouchSlopProvider +import com.hippo.ehviewer.ui.tools.SwipeToDismissBox2 import com.hippo.ehviewer.util.containsIgnoreCase import com.hippo.ehviewer.util.findActivity import com.hippo.ehviewer.util.mapToLongArray @@ -256,61 +255,59 @@ fun DownloadsScreen(navigator: NavController) { }, ) ReorderableItem(reorderableLabelState, key = item) { isDragging -> - LocalTouchSlopProvider(Settings.touchSlopFactor.toFloat()) { - SwipeToDismissBox( - state = dismissState, - backgroundContent = {}, - directions = setOf(DismissDirection.EndToStart), - ) { - val elevation by animateDpAsState( - if (isDragging) { - 8.dp // md.sys.elevation.level4 - } else { - 1.dp // md.sys.elevation.level1 - }, - label = "elevation", - ) - val thatList = DownloadManager.getLabelDownloadInfoList(item) - val text = if (thatList != null) "$item [${thatList.size}]" else item - ListItem( - modifier = Modifier.clickable { - label = item - closeSheet() - }, - tonalElevation = 1.dp, - shadowElevation = elevation, - headlineContent = { - Text(text) - }, - trailingContent = { - Row { - IconButton( - onClick = { - coroutineScope.launch { - val new = dialogState.awaitInputText(title = newLabel, hint = labelsStr) { text -> - when { - text.isBlank() -> labelEmpty - text == defaultName -> defaultInvalid - DownloadManager.containLabel(text) -> labelExists - else -> null - } + SwipeToDismissBox2( + state = dismissState, + backgroundContent = {}, + directions = setOf(DismissDirection.EndToStart), + ) { + val elevation by animateDpAsState( + if (isDragging) { + 8.dp // md.sys.elevation.level4 + } else { + 1.dp // md.sys.elevation.level1 + }, + label = "elevation", + ) + val thatList = DownloadManager.getLabelDownloadInfoList(item) + val text = if (thatList != null) "$item [${thatList.size}]" else item + ListItem( + modifier = Modifier.clickable { + label = item + closeSheet() + }, + tonalElevation = 1.dp, + shadowElevation = elevation, + headlineContent = { + Text(text) + }, + trailingContent = { + Row { + IconButton( + onClick = { + coroutineScope.launch { + val new = dialogState.awaitInputText(title = newLabel, hint = labelsStr) { text -> + when { + text.isBlank() -> labelEmpty + text == defaultName -> defaultInvalid + DownloadManager.containLabel(text) -> labelExists + else -> null } - DownloadManager.renameLabel(item, new) } - }, - ) { - Icon(imageVector = Icons.Default.Edit, contentDescription = null) - } - IconButton( - onClick = {}, - modifier = Modifier.draggableHandle(), - ) { - Icon(imageVector = Icons.Default.Reorder, contentDescription = null) - } + DownloadManager.renameLabel(item, new) + } + }, + ) { + Icon(imageVector = Icons.Default.Edit, contentDescription = null) } - }, - ) - } + IconButton( + onClick = {}, + modifier = Modifier.draggableHandle(), + ) { + Icon(imageVector = Icons.Default.Reorder, contentDescription = null) + } + } + }, + ) } } } diff --git a/app/src/main/kotlin/com/hippo/ehviewer/ui/scene/GalleryListFragment.kt b/app/src/main/kotlin/com/hippo/ehviewer/ui/scene/GalleryListFragment.kt index 6c099bf2d..ec9ba761c 100644 --- a/app/src/main/kotlin/com/hippo/ehviewer/ui/scene/GalleryListFragment.kt +++ b/app/src/main/kotlin/com/hippo/ehviewer/ui/scene/GalleryListFragment.kt @@ -58,7 +58,6 @@ import androidx.compose.material3.MaterialTheme import androidx.compose.material3.PrimaryTabRow import androidx.compose.material3.SnackbarHost import androidx.compose.material3.SnackbarHostState -import androidx.compose.material3.SwipeToDismissBox import androidx.compose.material3.Text import androidx.compose.material3.TopAppBar import androidx.compose.material3.pulltorefresh.rememberPullToRefreshState @@ -66,7 +65,6 @@ import androidx.compose.material3.rememberDismissState import androidx.compose.material3.windowsizeclass.WindowWidthSizeClass import androidx.compose.material3.windowsizeclass.calculateWindowSizeClass import androidx.compose.runtime.Composable -import androidx.compose.runtime.CompositionLocalProvider import androidx.compose.runtime.LaunchedEffect import androidx.compose.runtime.Stable import androidx.compose.runtime.getValue @@ -89,7 +87,6 @@ import androidx.compose.ui.input.nestedscroll.nestedScroll import androidx.compose.ui.platform.LocalContext import androidx.compose.ui.platform.LocalLayoutDirection import androidx.compose.ui.platform.LocalView -import androidx.compose.ui.platform.LocalViewConfiguration import androidx.compose.ui.res.dimensionResource import androidx.compose.ui.res.stringArrayResource import androidx.compose.ui.res.stringResource @@ -152,7 +149,7 @@ import com.hippo.ehviewer.ui.main.SearchAdvanced import com.hippo.ehviewer.ui.scene.GalleryListFragment.Companion.toStartArgs import com.hippo.ehviewer.ui.tools.Deferred import com.hippo.ehviewer.ui.tools.LocalDialogState -import com.hippo.ehviewer.ui.tools.LocalTouchSlopProvider +import com.hippo.ehviewer.ui.tools.SwipeToDismissBox2 import com.hippo.ehviewer.ui.tools.animateFloatMergePredictiveBackAsState import com.hippo.ehviewer.ui.tools.observed import com.hippo.ehviewer.ui.tools.rememberInVM @@ -450,75 +447,70 @@ fun GalleryListScreen(lub: ListUrlBuilder, navigator: NavController) { true }, ) - val viewConfiguration = LocalViewConfiguration.current - LocalTouchSlopProvider(Settings.touchSlopFactor.toFloat()) { - SwipeToDismissBox( - state = dismissState, - backgroundContent = {}, - directions = setOf(DismissDirection.EndToStart), - ) { - val elevation by animateDpAsState( - if (isDragging) { - 8.dp // md.sys.elevation.level4 + SwipeToDismissBox2( + state = dismissState, + backgroundContent = {}, + directions = setOf(DismissDirection.EndToStart), + ) { + val elevation by animateDpAsState( + if (isDragging) { + 8.dp // md.sys.elevation.level4 + } else { + 1.dp // md.sys.elevation.level1 + }, + label = "elevation", + ) + ListItem( + modifier = Modifier.clickable { + if (urlBuilder.mode == MODE_WHATS_HOT) { + navigator.navAnimated(R.id.galleryListScene, ListUrlBuilder(item).toStartArgs()) } else { - 1.dp // md.sys.elevation.level1 - }, - label = "elevation", - ) - ListItem( - modifier = Modifier.clickable { - if (urlBuilder.mode == MODE_WHATS_HOT) { - navigator.navAnimated(R.id.galleryListScene, ListUrlBuilder(item).toStartArgs()) - } else { - urlBuilder = ListUrlBuilder(item) - data.refresh() - } - showSearchLayout = false - coroutineScope.launch { sheetState.close() } - }, - tonalElevation = 1.dp, - shadowElevation = elevation, - headlineContent = { - Text(text = item.name) - }, - trailingContent = { - CompositionLocalProvider(LocalViewConfiguration provides viewConfiguration) { - IconButton( - onClick = {}, - modifier = Modifier.draggableHandle( - onDragStarted = { - val feedbackConstant = if (isAtLeastU) { - HapticFeedbackConstants.DRAG_START - } else if (isAtLeastR) { - HapticFeedbackConstants.GESTURE_START - } else if (isAtLeastOMR1) { - HapticFeedbackConstants.KEYBOARD_PRESS - } else { - HapticFeedbackConstants.VIRTUAL_KEY - } - view.performHapticFeedback(feedbackConstant) - }, - onDragStopped = { - val feedbackConstant = if (isAtLeastR) { - HapticFeedbackConstants.GESTURE_END - } else if (isAtLeastOMR1) { - HapticFeedbackConstants.KEYBOARD_RELEASE - } else { - HapticFeedbackConstants.VIRTUAL_KEY_RELEASE - } - view.performHapticFeedback(feedbackConstant) - }, - ), - ) { - Icon( - imageVector = Icons.Default.Reorder, - contentDescription = null, - ) - } - } - }, - ) - } + urlBuilder = ListUrlBuilder(item) + data.refresh() + } + showSearchLayout = false + coroutineScope.launch { sheetState.close() } + }, + tonalElevation = 1.dp, + shadowElevation = elevation, + headlineContent = { + Text(text = item.name) + }, + trailingContent = { + IconButton( + onClick = {}, + modifier = Modifier.draggableHandle( + onDragStarted = { + val feedbackConstant = if (isAtLeastU) { + HapticFeedbackConstants.DRAG_START + } else if (isAtLeastR) { + HapticFeedbackConstants.GESTURE_START + } else if (isAtLeastOMR1) { + HapticFeedbackConstants.KEYBOARD_PRESS + } else { + HapticFeedbackConstants.VIRTUAL_KEY + } + view.performHapticFeedback(feedbackConstant) + }, + onDragStopped = { + val feedbackConstant = if (isAtLeastR) { + HapticFeedbackConstants.GESTURE_END + } else if (isAtLeastOMR1) { + HapticFeedbackConstants.KEYBOARD_RELEASE + } else { + HapticFeedbackConstants.VIRTUAL_KEY_RELEASE + } + view.performHapticFeedback(feedbackConstant) + }, + ), + ) { + Icon( + imageVector = Icons.Default.Reorder, + contentDescription = null, + ) + } + }, + ) } } } diff --git a/app/src/main/kotlin/com/hippo/ehviewer/ui/scene/HistoryFragment.kt b/app/src/main/kotlin/com/hippo/ehviewer/ui/scene/HistoryFragment.kt index 1b574d76a..17a55c050 100644 --- a/app/src/main/kotlin/com/hippo/ehviewer/ui/scene/HistoryFragment.kt +++ b/app/src/main/kotlin/com/hippo/ehviewer/ui/scene/HistoryFragment.kt @@ -21,7 +21,6 @@ import androidx.compose.material3.Icon import androidx.compose.material3.IconButton import androidx.compose.material3.MaterialTheme import androidx.compose.material3.Scaffold -import androidx.compose.material3.SwipeToDismissBox import androidx.compose.material3.Text import androidx.compose.material3.TopAppBar import androidx.compose.material3.TopAppBarDefaults @@ -49,7 +48,6 @@ import androidx.paging.compose.itemContentType import androidx.paging.compose.itemKey import com.hippo.ehviewer.EhDB import com.hippo.ehviewer.R -import com.hippo.ehviewer.Settings import com.hippo.ehviewer.icons.EhIcons import com.hippo.ehviewer.icons.big.History import com.hippo.ehviewer.ui.MainActivity @@ -58,7 +56,7 @@ import com.hippo.ehviewer.ui.main.GalleryInfoListItem import com.hippo.ehviewer.ui.tools.Deferred import com.hippo.ehviewer.ui.tools.FastScrollLazyColumn import com.hippo.ehviewer.ui.tools.LocalDialogState -import com.hippo.ehviewer.ui.tools.LocalTouchSlopProvider +import com.hippo.ehviewer.ui.tools.SwipeToDismissBox2 import com.hippo.ehviewer.ui.tools.rememberInVM import com.hippo.ehviewer.util.findActivity import com.ramcosta.composedestinations.annotation.Destination @@ -127,29 +125,27 @@ fun HistoryScreen(navigator: NavController) { true }, ) - LocalTouchSlopProvider(Settings.touchSlopFactor.toFloat()) { - SwipeToDismissBox( - state = dismissState, - backgroundContent = {}, - modifier = Modifier.animateItemPlacement(), - directions = setOf(DismissDirection.EndToStart), - ) { - GalleryInfoListItem( - onClick = { - navigator.navAnimated( - R.id.galleryDetailScene, - bundleOf(GalleryDetailFragment.KEY_ARGS to GalleryInfoArgs(info)), - ) - }, - onLongClick = { - coroutineScope.launchIO { - dialogState.doGalleryInfoAction(info, context) - } - }, - info = info, - modifier = Modifier.height(cardHeight), - ) - } + SwipeToDismissBox2( + state = dismissState, + backgroundContent = {}, + modifier = Modifier.animateItemPlacement(), + directions = setOf(DismissDirection.EndToStart), + ) { + GalleryInfoListItem( + onClick = { + navigator.navAnimated( + R.id.galleryDetailScene, + bundleOf(GalleryDetailFragment.KEY_ARGS to GalleryInfoArgs(info)), + ) + }, + onLongClick = { + coroutineScope.launchIO { + dialogState.doGalleryInfoAction(info, context) + } + }, + info = info, + modifier = Modifier.height(cardHeight), + ) } } else { Spacer(modifier = Modifier.height(cardHeight).fillMaxWidth()) diff --git a/app/src/main/kotlin/com/hippo/ehviewer/ui/tools/SwipeToDismissBox2.kt b/app/src/main/kotlin/com/hippo/ehviewer/ui/tools/SwipeToDismissBox2.kt new file mode 100644 index 000000000..53a390c75 --- /dev/null +++ b/app/src/main/kotlin/com/hippo/ehviewer/ui/tools/SwipeToDismissBox2.kt @@ -0,0 +1,37 @@ +package com.hippo.ehviewer.ui.tools + +import androidx.compose.foundation.layout.RowScope +import androidx.compose.material3.DismissDirection +import androidx.compose.material3.DismissState +import androidx.compose.material3.SwipeToDismissBox +import androidx.compose.runtime.Composable +import androidx.compose.runtime.CompositionLocalProvider +import androidx.compose.ui.Modifier +import androidx.compose.ui.platform.LocalViewConfiguration +import com.hippo.ehviewer.Settings + +@Composable +fun SwipeToDismissBox2( + state: DismissState, + backgroundContent: @Composable RowScope.() -> Unit, + modifier: Modifier = Modifier, + directions: Set = setOf( + DismissDirection.EndToStart, + DismissDirection.StartToEnd, + ), + content: @Composable RowScope.() -> Unit, +) { + val viewConfiguration = LocalViewConfiguration.current + LocalTouchSlopProvider(Settings.touchSlopFactor.toFloat()) { + SwipeToDismissBox( + state = state, + backgroundContent = backgroundContent, + modifier = modifier, + directions = directions, + ) { + CompositionLocalProvider(LocalViewConfiguration provides viewConfiguration) { + content() + } + } + } +}