Add the ability to explicitely remove items from frequently used items
Close #113
This commit is contained in:
parent
91e68cd8d3
commit
db7db74d2d
@ -160,4 +160,7 @@ interface SearchDao {
|
|||||||
|
|
||||||
@Query("UPDATE Searchable SET `pinned` = 0")
|
@Query("UPDATE Searchable SET `pinned` = 0")
|
||||||
fun unpinAll()
|
fun unpinAll()
|
||||||
|
|
||||||
|
@Query("UPDATE Searchable Set `pinned` = 0, `launchCount` = 0 WHERE `key` = :key")
|
||||||
|
suspend fun resetPinStatusAndLaunchCounter(key: String)
|
||||||
}
|
}
|
||||||
|
|||||||
@ -54,14 +54,23 @@ interface FavoritesRepository {
|
|||||||
fun unhideItem(searchable: Searchable)
|
fun unhideItem(searchable: Searchable)
|
||||||
fun incrementLaunchCounter(searchable: Searchable)
|
fun incrementLaunchCounter(searchable: Searchable)
|
||||||
fun updateFavorites(
|
fun updateFavorites(
|
||||||
manuallySorted: List<Searchable>,
|
manuallySorted: List<Searchable>,
|
||||||
automaticallySorted: List<Searchable>,
|
automaticallySorted: List<Searchable>,
|
||||||
)
|
)
|
||||||
|
|
||||||
fun getHiddenItems(): Flow<List<Searchable>>
|
fun getHiddenItems(): Flow<List<Searchable>>
|
||||||
fun getHiddenItemKeys(): Flow<List<String>>
|
fun getHiddenItemKeys(): Flow<List<String>>
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Remove this item from the Searchable database
|
||||||
|
*/
|
||||||
fun remove(searchable: Searchable)
|
fun remove(searchable: Searchable)
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Remove this item from favorites and reset launch counter
|
||||||
|
*/
|
||||||
|
fun removeFromFavorites(searchable: Searchable)
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Ensure that this searchable exists in the Favorites table.
|
* Ensure that this searchable exists in the Favorites table.
|
||||||
* If it doesn't exist, insert it with 0 launch count, not pinned and not hidden
|
* If it doesn't exist, insert it with 0 launch count, not pinned and not hidden
|
||||||
@ -287,6 +296,12 @@ internal class FavoritesRepositoryImpl(
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
override fun removeFromFavorites(searchable: Searchable) {
|
||||||
|
scope.launch {
|
||||||
|
database.searchDao().resetPinStatusAndLaunchCounter(searchable.key)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
override fun save(searchable: Searchable) {
|
override fun save(searchable: Searchable) {
|
||||||
scope.launch {
|
scope.launch {
|
||||||
withContext(Dispatchers.IO) {
|
withContext(Dispatchers.IO) {
|
||||||
@ -322,17 +337,18 @@ internal class FavoritesRepositoryImpl(
|
|||||||
entity.pinPosition = manuallySorted.size - index + 1
|
entity.pinPosition = manuallySorted.size - index + 1
|
||||||
entity
|
entity
|
||||||
}
|
}
|
||||||
val updatedAutomaticallySorted = automaticallySorted.mapIndexedNotNull { index, searchable ->
|
val updatedAutomaticallySorted =
|
||||||
val entity = entities.find { searchable.key == it.key } ?: FavoritesItem(
|
automaticallySorted.mapIndexedNotNull { index, searchable ->
|
||||||
key = searchable.key,
|
val entity = entities.find { searchable.key == it.key } ?: FavoritesItem(
|
||||||
searchable = searchable,
|
key = searchable.key,
|
||||||
launchCount = 0,
|
searchable = searchable,
|
||||||
pinPosition = 0,
|
launchCount = 0,
|
||||||
hidden = false,
|
pinPosition = 0,
|
||||||
).toDatabaseEntity() ?: return@mapIndexedNotNull null
|
hidden = false,
|
||||||
entity.pinPosition = 1
|
).toDatabaseEntity() ?: return@mapIndexedNotNull null
|
||||||
entity
|
entity.pinPosition = 1
|
||||||
}
|
entity
|
||||||
|
}
|
||||||
database.runInTransaction {
|
database.runInTransaction {
|
||||||
dao.unpinAll()
|
dao.unpinAll()
|
||||||
dao.insertAllReplaceExisting(updatedManuallySorted)
|
dao.insertAllReplaceExisting(updatedManuallySorted)
|
||||||
@ -439,7 +455,10 @@ internal class FavoritesRepositoryImpl(
|
|||||||
if (item.searchable == null || item.searchable.key != item.key) {
|
if (item.searchable == null || item.searchable.key != item.key) {
|
||||||
removeInvalidItem(item.key)
|
removeInvalidItem(item.key)
|
||||||
removed++
|
removed++
|
||||||
Log.i("MM20", "SearchableDatabase cleanup: removed invalid item ${item.key}")
|
Log.i(
|
||||||
|
"MM20",
|
||||||
|
"SearchableDatabase cleanup: removed invalid item ${item.key}"
|
||||||
|
)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
page++
|
page++
|
||||||
|
|||||||
@ -31,6 +31,7 @@ import kotlin.coroutines.coroutineContext
|
|||||||
fun rememberLazyDragAndDropGridState(
|
fun rememberLazyDragAndDropGridState(
|
||||||
gridState: LazyGridState = rememberLazyGridState(),
|
gridState: LazyGridState = rememberLazyGridState(),
|
||||||
onDragStart: (item: LazyGridItemInfo) -> Boolean = { true },
|
onDragStart: (item: LazyGridItemInfo) -> Boolean = { true },
|
||||||
|
onDrag: (item: LazyGridItemInfo, offset: Offset) -> Unit = {_, _ ->},
|
||||||
onDragEnd: (item: LazyGridItemInfo) -> Unit = {},
|
onDragEnd: (item: LazyGridItemInfo) -> Unit = {},
|
||||||
onDragCancel: (item: LazyGridItemInfo) -> Unit = {},
|
onDragCancel: (item: LazyGridItemInfo) -> Unit = {},
|
||||||
onItemMove: (from: LazyGridItemInfo, to: LazyGridItemInfo) -> Unit
|
onItemMove: (from: LazyGridItemInfo, to: LazyGridItemInfo) -> Unit
|
||||||
@ -39,6 +40,7 @@ fun rememberLazyDragAndDropGridState(
|
|||||||
LazyDragAndDropGridState(
|
LazyDragAndDropGridState(
|
||||||
gridState,
|
gridState,
|
||||||
onDragStart,
|
onDragStart,
|
||||||
|
onDrag,
|
||||||
onDragEnd,
|
onDragEnd,
|
||||||
onDragCancel,
|
onDragCancel,
|
||||||
onItemMove
|
onItemMove
|
||||||
@ -49,6 +51,7 @@ fun rememberLazyDragAndDropGridState(
|
|||||||
data class LazyDragAndDropGridState(
|
data class LazyDragAndDropGridState(
|
||||||
val gridState: LazyGridState,
|
val gridState: LazyGridState,
|
||||||
val onDragStart: (item: LazyGridItemInfo) -> Boolean = { true },
|
val onDragStart: (item: LazyGridItemInfo) -> Boolean = { true },
|
||||||
|
val onDrag: (item: LazyGridItemInfo, offset: Offset) -> Unit = {_, _ ->},
|
||||||
val onDragEnd: (item: LazyGridItemInfo) -> Unit = {},
|
val onDragEnd: (item: LazyGridItemInfo) -> Unit = {},
|
||||||
val onDragCancel: (item: LazyGridItemInfo) -> Unit = {},
|
val onDragCancel: (item: LazyGridItemInfo) -> Unit = {},
|
||||||
val onItemMove: (from: LazyGridItemInfo, to: LazyGridItemInfo) -> Unit
|
val onItemMove: (from: LazyGridItemInfo, to: LazyGridItemInfo) -> Unit
|
||||||
@ -259,7 +262,7 @@ fun Modifier.dragAndDrop(
|
|||||||
).contains(draggedCenter)
|
).contains(draggedCenter)
|
||||||
}
|
}
|
||||||
|
|
||||||
if (dragOver != null && dragOver.key != state.draggedItem?.key) {
|
if (dragOver != null && dragOver.key != draggedItem.key) {
|
||||||
scope.launch {
|
scope.launch {
|
||||||
state.attemptMove(dragOver)
|
state.attemptMove(dragOver)
|
||||||
}
|
}
|
||||||
@ -280,6 +283,8 @@ fun Modifier.dragAndDrop(
|
|||||||
} else {
|
} else {
|
||||||
state.endScrolling()
|
state.endScrolling()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
state.draggedItemOffset?.let { state.onDrag(draggedItem, it) }
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
onDragCancel = {
|
onDragCancel = {
|
||||||
|
|||||||
@ -14,6 +14,7 @@ import androidx.compose.foundation.lazy.grid.GridItemSpan
|
|||||||
import androidx.compose.foundation.lazy.items
|
import androidx.compose.foundation.lazy.items
|
||||||
import androidx.compose.material.icons.Icons
|
import androidx.compose.material.icons.Icons
|
||||||
import androidx.compose.material.icons.rounded.Add
|
import androidx.compose.material.icons.rounded.Add
|
||||||
|
import androidx.compose.material.icons.rounded.Delete
|
||||||
import androidx.compose.material3.*
|
import androidx.compose.material3.*
|
||||||
import androidx.compose.runtime.*
|
import androidx.compose.runtime.*
|
||||||
import androidx.compose.runtime.livedata.observeAsState
|
import androidx.compose.runtime.livedata.observeAsState
|
||||||
@ -112,9 +113,23 @@ fun ReorderFavoritesGrid(viewModel: EditFavoritesSheetVM) {
|
|||||||
val items by viewModel.gridItems.observeAsState(emptyList())
|
val items by viewModel.gridItems.observeAsState(emptyList())
|
||||||
val columns = LocalGridColumns.current
|
val columns = LocalGridColumns.current
|
||||||
|
|
||||||
|
var contextMenuItemKey by remember { mutableStateOf<String?>(null) }
|
||||||
|
|
||||||
|
val contextMenuCloseDistance = 8.dp.toPixels()
|
||||||
|
|
||||||
val state = rememberLazyDragAndDropGridState(
|
val state = rememberLazyDragAndDropGridState(
|
||||||
onDragStart = {
|
onDragStart = {
|
||||||
items.getOrNull(it.index) is FavoritesSheetGridItem.Favorite
|
val item = items.getOrNull(it.index)
|
||||||
|
|
||||||
|
if (item !is FavoritesSheetGridItem.Favorite) return@rememberLazyDragAndDropGridState false
|
||||||
|
|
||||||
|
contextMenuItemKey = item.item.key
|
||||||
|
true
|
||||||
|
},
|
||||||
|
onDrag = { _, offset ->
|
||||||
|
if (offset.getDistanceSquared() > contextMenuCloseDistance) {
|
||||||
|
contextMenuItemKey = null
|
||||||
|
}
|
||||||
}
|
}
|
||||||
) { from, to ->
|
) { from, to ->
|
||||||
viewModel.moveItem(from, to)
|
viewModel.moveItem(from, to)
|
||||||
@ -163,6 +178,23 @@ fun ReorderFavoritesGrid(viewModel: EditFavoritesSheetVM) {
|
|||||||
icon = icon,
|
icon = icon,
|
||||||
badge = badge
|
badge = badge
|
||||||
)
|
)
|
||||||
|
if (contextMenuItemKey == it.item.key) {
|
||||||
|
DropdownMenu(
|
||||||
|
expanded = true,
|
||||||
|
onDismissRequest = { contextMenuItemKey = null }) {
|
||||||
|
DropdownMenuItem(
|
||||||
|
leadingIcon = {
|
||||||
|
Icon(imageVector = Icons.Rounded.Delete, contentDescription = null)
|
||||||
|
},
|
||||||
|
text = {
|
||||||
|
Text("Remove")
|
||||||
|
}, onClick = {
|
||||||
|
contextMenuItemKey?.let { viewModel.remove(it) }
|
||||||
|
contextMenuItemKey = null
|
||||||
|
}
|
||||||
|
)
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
is FavoritesSheetGridItem.Divider -> {
|
is FavoritesSheetGridItem.Divider -> {
|
||||||
@ -331,8 +363,11 @@ fun ShortcutPicker(viewModel: EditFavoritesSheetVM) {
|
|||||||
.fillMaxWidth()
|
.fillMaxWidth()
|
||||||
.padding(vertical = 4.dp),
|
.padding(vertical = 4.dp),
|
||||||
onClick = {
|
onClick = {
|
||||||
val launcherApps = context.getSystemService(Context.LAUNCHER_APPS_SERVICE) as LauncherApps
|
val launcherApps =
|
||||||
val sender = launcherApps.getShortcutConfigActivityIntent(it.launcherActivityInfo) ?: return@OutlinedCard
|
context.getSystemService(Context.LAUNCHER_APPS_SERVICE) as LauncherApps
|
||||||
|
val sender =
|
||||||
|
launcherApps.getShortcutConfigActivityIntent(it.launcherActivityInfo)
|
||||||
|
?: return@OutlinedCard
|
||||||
activityLauncher.launch(IntentSenderRequest.Builder(sender).build(), null)
|
activityLauncher.launch(IntentSenderRequest.Builder(sender).build(), null)
|
||||||
}) {
|
}) {
|
||||||
Row(
|
Row(
|
||||||
|
|||||||
@ -202,5 +202,15 @@ class EditFavoritesSheetVM : ViewModel(), KoinComponent {
|
|||||||
createShortcutTarget.value = null
|
createShortcutTarget.value = null
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fun remove(key: String) {
|
||||||
|
val gridItems = gridItems.value?.toMutableList() ?: return
|
||||||
|
val item = gridItems.find { it is FavoritesSheetGridItem.Favorite && it.item.key == key } as FavoritesSheetGridItem.Favorite?
|
||||||
|
if (item != null) {
|
||||||
|
repository.removeFromFavorites(item.item)
|
||||||
|
gridItems.remove(item)
|
||||||
|
this.gridItems.value = gridItems
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
}
|
}
|
||||||
Loading…
x
Reference in New Issue
Block a user