Add haptic feedback for drag and drop in Downloads

This commit is contained in:
FooIbar committed 2023-11-26 22:32:04 +08:00
1 parent 5dad21f4ea
commit 86a49f764e
4 files changed
+72 -62

No files matched your search

@@ -9,7 +9,6 @@ import androidx.compose.foundation.layout.padding
import androidx.compose.material.icons.Icons
import androidx.compose.material.icons.filled.Pause
import androidx.compose.material.icons.filled.PlayArrow
import androidx.compose.material.icons.filled.Reorder
import androidx.compose.material3.Card
import androidx.compose.material3.Icon
import androidx.compose.material3.IconButton
@@ -49,6 +48,7 @@ import com.hippo.ehviewer.download.downloadDir
import com.hippo.ehviewer.ktbuilder.imageRequest
import com.hippo.ehviewer.ui.tools.CropDefaults
import com.hippo.ehviewer.ui.tools.CrystalCard
import com.hippo.ehviewer.ui.tools.DragHandle
import com.hippo.ehviewer.ui.tools.GalleryListCardRating
import com.hippo.ehviewer.util.FileUtils
import com.hippo.ehviewer.util.sendTo
@@ -242,15 +242,7 @@ fun ReorderableItemScope.DownloadCard(
bottom.linkTo(parent.bottom)
},
) {
IconButton(
onClick = { },
modifier = Modifier.draggableHandle(),
) {
Icon(
imageVector = Icons.Default.Reorder,
contentDescription = null,
)
}
DragHandle()
if (downloadState == DownloadInfo.STATE_WAIT || downloadState == DownloadInfo.STATE_DOWNLOAD) {
IconButton(onClick = onStop) {
Icon(imageVector = Icons.Default.Pause, contentDescription = null)
@@ -37,7 +37,6 @@ import androidx.compose.material.icons.filled.Edit
import androidx.compose.material.icons.filled.MoreVert
import androidx.compose.material.icons.filled.Pause
import androidx.compose.material.icons.filled.PlayArrow
import androidx.compose.material.icons.filled.Reorder
import androidx.compose.material3.DismissDirection
import androidx.compose.material3.DismissValue
import androidx.compose.material3.DropdownMenu
@@ -66,6 +65,7 @@ import androidx.compose.ui.input.nestedscroll.NestedScrollSource
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.res.dimensionResource
import androidx.compose.ui.res.stringArrayResource
import androidx.compose.ui.res.stringResource
@@ -89,9 +89,11 @@ import com.hippo.ehviewer.ui.main.FabLayout
import com.hippo.ehviewer.ui.navToReader
import com.hippo.ehviewer.ui.showMoveDownloadLabelList
import com.hippo.ehviewer.ui.tools.Deferred
import com.hippo.ehviewer.ui.tools.DragHandle
import com.hippo.ehviewer.ui.tools.FastScrollLazyColumn
import com.hippo.ehviewer.ui.tools.LocalDialogState
import com.hippo.ehviewer.ui.tools.SwipeToDismissBox2
import com.hippo.ehviewer.ui.tools.draggingHapticFeedback
import com.hippo.ehviewer.util.containsIgnoreCase
import com.hippo.ehviewer.util.findActivity
import com.hippo.ehviewer.util.mapToLongArray
@@ -123,6 +125,7 @@ fun DownloadsScreen(navigator: NavController) {
val activity = remember(context) { context.findActivity<MainActivity>() }
val coroutineScope = rememberCoroutineScope()
val dialogState = LocalDialogState.current
val view = LocalView.current
val title = stringResource(R.string.scene_download_title, label ?: stringResource(R.string.download_all))
val hint = stringResource(R.string.search_bar_hint, title)
val defaultName = stringResource(R.string.default_download_label_name)
@@ -208,6 +211,7 @@ fun DownloadsScreen(navigator: NavController) {
coroutineScope.launch {
DownloadManager.moveLabel(from.index - 2, to.index - 2)
}
view.performHapticFeedback(draggingHapticFeedback)
}
LazyColumn(
@@ -299,12 +303,7 @@ fun DownloadsScreen(navigator: NavController) {
) {
Icon(imageVector = Icons.Default.Edit, contentDescription = null)
}
IconButton(
onClick = {},
modifier = Modifier.draggableHandle(),
) {
Icon(imageVector = Icons.Default.Reorder, contentDescription = null)
}
DragHandle()
}
},
)
@@ -412,6 +411,7 @@ fun DownloadsScreen(navigator: NavController) {
coroutineScope.launchIO {
EhDB.updateDownloadInfo(newList)
}
view.performHapticFeedback(draggingHapticFeedback)
}
FastScrollLazyColumn(
modifier = Modifier.nestedScroll(searchBarConnection),
@@ -3,7 +3,6 @@ package com.hippo.ehviewer.ui.scene
import android.graphics.Bitmap
import android.net.Uri
import android.os.Bundle
import android.view.HapticFeedbackConstants
import android.view.LayoutInflater
import android.view.View
import android.view.ViewConfiguration
@@ -43,7 +42,6 @@ import androidx.compose.material.icons.automirrored.filled.LastPage
import androidx.compose.material.icons.filled.Add
import androidx.compose.material.icons.filled.ImageSearch
import androidx.compose.material.icons.filled.Refresh
import androidx.compose.material.icons.filled.Reorder
import androidx.compose.material.icons.filled.Translate
import androidx.compose.material.icons.outlined.Bookmarks
import androidx.compose.material3.DismissDirection
@@ -148,17 +146,16 @@ import com.hippo.ehviewer.ui.main.NormalSearch
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.DragHandle
import com.hippo.ehviewer.ui.tools.LocalDialogState
import com.hippo.ehviewer.ui.tools.SwipeToDismissBox2
import com.hippo.ehviewer.ui.tools.animateFloatMergePredictiveBackAsState
import com.hippo.ehviewer.ui.tools.draggingHapticFeedback
import com.hippo.ehviewer.ui.tools.observed
import com.hippo.ehviewer.ui.tools.rememberInVM
import com.hippo.ehviewer.util.AppConfig
import com.hippo.ehviewer.util.findActivity
import com.hippo.ehviewer.util.getParcelableCompat
import com.hippo.ehviewer.util.isAtLeastOMR1
import com.hippo.ehviewer.util.isAtLeastR
import com.hippo.ehviewer.util.isAtLeastU
import com.hippo.ehviewer.util.pickVisualMedia
import com.ramcosta.composedestinations.annotation.Destination
import eu.kanade.tachiyomi.util.lang.launchIO
@@ -416,14 +413,7 @@ fun GalleryListScreen(lub: ListUrlBuilder, navigator: NavController) {
list.zip(range).forEach { it.first.position = it.second }
EhDB.updateQuickSearch(list)
}
val feedbackConstant = if (isAtLeastU) {
HapticFeedbackConstants.SEGMENT_FREQUENT_TICK
} else if (isAtLeastOMR1) {
HapticFeedbackConstants.TEXT_HANDLE_MOVE
} else {
HapticFeedbackConstants.CLOCK_TICK
}
view.performHapticFeedback(feedbackConstant)
view.performHapticFeedback(draggingHapticFeedback)
}
LazyColumn(
modifier = Modifier.fillMaxSize(),
@@ -477,38 +467,7 @@ fun GalleryListScreen(lub: ListUrlBuilder, navigator: NavController) {
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,
)
}
DragHandle()
},
)
}
@@ -0,0 +1,59 @@
package com.hippo.ehviewer.ui.tools
import android.view.HapticFeedbackConstants
import androidx.compose.material.icons.Icons
import androidx.compose.material.icons.filled.Reorder
import androidx.compose.material3.Icon
import androidx.compose.material3.IconButton
import androidx.compose.runtime.Composable
import androidx.compose.ui.Modifier
import androidx.compose.ui.platform.LocalView
import com.hippo.ehviewer.util.isAtLeastOMR1
import com.hippo.ehviewer.util.isAtLeastR
import com.hippo.ehviewer.util.isAtLeastU
import sh.calvin.reorderable.ReorderableItemScope
@Composable
fun ReorderableItemScope.DragHandle(modifier: Modifier = Modifier) {
val view = LocalView.current
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,
)
}
}
val draggingHapticFeedback = if (isAtLeastU) {
HapticFeedbackConstants.SEGMENT_FREQUENT_TICK
} else if (isAtLeastOMR1) {
HapticFeedbackConstants.TEXT_HANDLE_MOVE
} else {
HapticFeedbackConstants.CLOCK_TICK
}