Fix download label drag and drop
This commit is contained in:
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()
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
Reference in new issue
Block a user