Fix download label drag and drop

This commit is contained in:
FooIbar committed 2023-11-26 21:57:21 +08:00
1 parent a4e9291bf9
commit 5dad21f4ea
4 files changed
+174 -152

No files matched your search

@@ -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)
}
}
},
)
}
}
}
@@ -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,
)
}
},
)
}
}
}
@@ -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())
@@ -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<DismissDirection> = 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()
}
}
}
}