Display undo snackbar after hiding an item
This commit is contained in:
parent
b784ab5aa5
commit
2c41d05ed3
@ -7,14 +7,14 @@ import android.os.Bundle
|
||||
import androidx.activity.compose.setContent
|
||||
import androidx.activity.viewModels
|
||||
import androidx.compose.foundation.background
|
||||
import androidx.compose.foundation.layout.Box
|
||||
import androidx.compose.foundation.layout.fillMaxSize
|
||||
import androidx.compose.foundation.layout.imePadding
|
||||
import androidx.compose.foundation.layout.systemBarsPadding
|
||||
import androidx.compose.foundation.layout.*
|
||||
import androidx.compose.material3.SnackbarHost
|
||||
import androidx.compose.material3.SnackbarHostState
|
||||
import androidx.compose.runtime.CompositionLocalProvider
|
||||
import androidx.compose.runtime.LaunchedEffect
|
||||
import androidx.compose.runtime.getValue
|
||||
import androidx.compose.runtime.livedata.observeAsState
|
||||
import androidx.compose.runtime.remember
|
||||
import androidx.compose.ui.Alignment
|
||||
import androidx.compose.ui.Modifier
|
||||
import androidx.compose.ui.geometry.Size
|
||||
@ -38,6 +38,7 @@ import de.mm20.launcher2.ui.launcher.modals.EditFavoritesView
|
||||
import de.mm20.launcher2.ui.launcher.modals.HiddenItemsSheet
|
||||
import de.mm20.launcher2.ui.launcher.transitions.HomeTransitionManager
|
||||
import de.mm20.launcher2.ui.launcher.transitions.LocalHomeTransitionManager
|
||||
import de.mm20.launcher2.ui.locals.LocalSnackbarHostState
|
||||
import de.mm20.launcher2.ui.locals.LocalWindowSize
|
||||
import de.mm20.launcher2.ui.theme.LauncherTheme
|
||||
import org.koin.android.ext.android.inject
|
||||
@ -61,9 +62,11 @@ class LauncherActivity : BaseActivity() {
|
||||
viewModel.setDarkMode(resources.configuration.uiMode and Configuration.UI_MODE_NIGHT_MASK == Configuration.UI_MODE_NIGHT_YES)
|
||||
|
||||
setContent {
|
||||
val snackbarHostState = remember { SnackbarHostState() }
|
||||
CompositionLocalProvider(
|
||||
LocalHomeTransitionManager provides homeTransitionManager,
|
||||
LocalWindowSize provides windowSize
|
||||
LocalWindowSize provides windowSize,
|
||||
LocalSnackbarHostState provides snackbarHostState
|
||||
) {
|
||||
LauncherTheme {
|
||||
ProvideSettings {
|
||||
@ -111,6 +114,10 @@ class LauncherActivity : BaseActivity() {
|
||||
}
|
||||
else -> {}
|
||||
}
|
||||
SnackbarHost(
|
||||
snackbarHostState,
|
||||
modifier = Modifier.navigationBarsPadding().imePadding()
|
||||
)
|
||||
}
|
||||
val showHiddenItems by viewModel.isHiddenItemsShown.observeAsState(false)
|
||||
if (showHiddenItems) {
|
||||
|
||||
@ -8,16 +8,19 @@ import androidx.compose.material.ExperimentalMaterialApi
|
||||
import androidx.compose.material.icons.Icons
|
||||
import androidx.compose.material.icons.rounded.*
|
||||
import androidx.compose.material3.MaterialTheme
|
||||
import androidx.compose.material3.SnackbarResult
|
||||
import androidx.compose.material3.Text
|
||||
import androidx.compose.runtime.*
|
||||
import androidx.compose.ui.Modifier
|
||||
import androidx.compose.ui.geometry.Rect
|
||||
import androidx.compose.ui.graphics.TransformOrigin
|
||||
import androidx.compose.ui.platform.LocalContext
|
||||
import androidx.compose.ui.platform.LocalLifecycleOwner
|
||||
import androidx.compose.ui.res.stringResource
|
||||
import androidx.compose.ui.text.style.TextOverflow
|
||||
import androidx.compose.ui.unit.dp
|
||||
import androidx.core.app.NotificationCompat
|
||||
import androidx.lifecycle.lifecycleScope
|
||||
import coil.compose.rememberImagePainter
|
||||
import com.google.accompanist.flowlayout.FlowRow
|
||||
import de.mm20.launcher2.search.data.Application
|
||||
@ -27,6 +30,7 @@ import de.mm20.launcher2.ui.ktx.toDp
|
||||
import de.mm20.launcher2.ui.ktx.toPixels
|
||||
import de.mm20.launcher2.ui.locals.LocalFavoritesEnabled
|
||||
import de.mm20.launcher2.ui.locals.LocalGridIconSize
|
||||
import de.mm20.launcher2.ui.locals.LocalSnackbarHostState
|
||||
import de.mm20.launcher2.ui.modifier.scale
|
||||
import kotlinx.coroutines.launch
|
||||
import kotlin.math.min
|
||||
@ -42,6 +46,9 @@ fun AppItem(
|
||||
) {
|
||||
val viewModel = remember { AppItemVM(app) }
|
||||
val context = LocalContext.current
|
||||
val lifecycleOwner = LocalLifecycleOwner.current
|
||||
val snackbarHostState = LocalSnackbarHostState.current
|
||||
|
||||
val scope = rememberCoroutineScope()
|
||||
Column(
|
||||
modifier = modifier
|
||||
@ -275,6 +282,16 @@ fun AppItem(
|
||||
action = {
|
||||
viewModel.hide()
|
||||
onBack()
|
||||
lifecycleOwner.lifecycleScope.launch {
|
||||
val result = snackbarHostState.showSnackbar(
|
||||
message = context.getString(R.string.msg_item_hidden, app.label),
|
||||
actionLabel = context.getString(R.string.action_undo),
|
||||
|
||||
)
|
||||
if(result == SnackbarResult.ActionPerformed) {
|
||||
viewModel.unhide()
|
||||
}
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
|
||||
@ -11,6 +11,7 @@ import androidx.compose.material.icons.Icons
|
||||
import androidx.compose.material.icons.rounded.*
|
||||
import androidx.compose.material3.Icon
|
||||
import androidx.compose.material3.MaterialTheme
|
||||
import androidx.compose.material3.SnackbarResult
|
||||
import androidx.compose.material3.Text
|
||||
import androidx.compose.runtime.Composable
|
||||
import androidx.compose.runtime.collectAsState
|
||||
@ -23,8 +24,10 @@ import androidx.compose.ui.geometry.Offset
|
||||
import androidx.compose.ui.geometry.Rect
|
||||
import androidx.compose.ui.graphics.Color
|
||||
import androidx.compose.ui.platform.LocalContext
|
||||
import androidx.compose.ui.platform.LocalLifecycleOwner
|
||||
import androidx.compose.ui.res.stringResource
|
||||
import androidx.compose.ui.unit.dp
|
||||
import androidx.lifecycle.lifecycleScope
|
||||
import de.mm20.launcher2.search.data.CalendarEvent
|
||||
import de.mm20.launcher2.ui.R
|
||||
import de.mm20.launcher2.ui.animation.animateTextStyleAsState
|
||||
@ -33,6 +36,8 @@ import de.mm20.launcher2.ui.component.Toolbar
|
||||
import de.mm20.launcher2.ui.component.ToolbarAction
|
||||
import de.mm20.launcher2.ui.ktx.toDp
|
||||
import de.mm20.launcher2.ui.locals.LocalFavoritesEnabled
|
||||
import de.mm20.launcher2.ui.locals.LocalSnackbarHostState
|
||||
import kotlinx.coroutines.launch
|
||||
|
||||
@Composable
|
||||
fun CalendarItem(
|
||||
@ -44,6 +49,9 @@ fun CalendarItem(
|
||||
val context = LocalContext.current
|
||||
val viewModel = remember(calendar.key) { CalendarItemVM(calendar) }
|
||||
|
||||
val lifecycleOwner = LocalLifecycleOwner.current
|
||||
val snackbarHostState = LocalSnackbarHostState.current
|
||||
|
||||
Row(
|
||||
modifier = modifier
|
||||
.drawBehind {
|
||||
@ -190,6 +198,16 @@ fun CalendarItem(
|
||||
action = {
|
||||
viewModel.hide()
|
||||
onBack()
|
||||
lifecycleOwner.lifecycleScope.launch {
|
||||
val result = snackbarHostState.showSnackbar(
|
||||
message = context.getString(R.string.msg_item_hidden, calendar.label),
|
||||
actionLabel = context.getString(R.string.action_undo),
|
||||
|
||||
)
|
||||
if(result == SnackbarResult.ActionPerformed) {
|
||||
viewModel.unhide()
|
||||
}
|
||||
}
|
||||
})
|
||||
}
|
||||
toolbarActions.add(hideAction)
|
||||
|
||||
@ -16,6 +16,7 @@ import androidx.compose.material.icons.rounded.StarOutline
|
||||
import androidx.compose.material.icons.rounded.Visibility
|
||||
import androidx.compose.material.icons.rounded.VisibilityOff
|
||||
import androidx.compose.material3.MaterialTheme
|
||||
import androidx.compose.material3.SnackbarResult
|
||||
import androidx.compose.runtime.*
|
||||
import androidx.compose.ui.Alignment
|
||||
import androidx.compose.ui.Modifier
|
||||
@ -24,8 +25,12 @@ import androidx.compose.ui.geometry.Rect
|
||||
import androidx.compose.ui.layout.boundsInWindow
|
||||
import androidx.compose.ui.layout.onGloballyPositioned
|
||||
import androidx.compose.ui.platform.LocalContext
|
||||
import androidx.compose.ui.platform.LocalLifecycleOwner
|
||||
import androidx.compose.ui.res.stringResource
|
||||
import androidx.compose.ui.unit.dp
|
||||
import androidx.lifecycle.lifecycleScope
|
||||
import de.mm20.launcher2.search.data.*
|
||||
import de.mm20.launcher2.ui.R
|
||||
import de.mm20.launcher2.ui.component.InnerCard
|
||||
import de.mm20.launcher2.ui.launcher.search.calendar.CalendarItem
|
||||
import de.mm20.launcher2.ui.launcher.search.contacts.ContactItem
|
||||
@ -33,6 +38,8 @@ import de.mm20.launcher2.ui.launcher.search.files.FileItem
|
||||
import de.mm20.launcher2.ui.launcher.search.shortcut.AppShortcutItem
|
||||
import de.mm20.launcher2.ui.locals.LocalCardStyle
|
||||
import de.mm20.launcher2.ui.locals.LocalFavoritesEnabled
|
||||
import de.mm20.launcher2.ui.locals.LocalSnackbarHostState
|
||||
import kotlinx.coroutines.launch
|
||||
|
||||
@OptIn(ExperimentalMaterialApi::class, androidx.compose.foundation.ExperimentalFoundationApi::class)
|
||||
@Composable
|
||||
@ -44,6 +51,9 @@ fun ListItem(modifier: Modifier = Modifier, item: Searchable) {
|
||||
val isPinned by viewModel.isPinned.collectAsState(false)
|
||||
val isHidden by viewModel.isHidden.collectAsState(false)
|
||||
|
||||
val lifecycleOwner = LocalLifecycleOwner.current
|
||||
val snackbarHostState = LocalSnackbarHostState.current
|
||||
|
||||
val dismissState = rememberDismissState(
|
||||
confirmStateChange = {
|
||||
when (it) {
|
||||
@ -54,7 +64,19 @@ fun ListItem(modifier: Modifier = Modifier, item: Searchable) {
|
||||
}
|
||||
DismissValue.DismissedToStart -> {
|
||||
if (isHidden) viewModel.unhide()
|
||||
else viewModel.hide()
|
||||
else {
|
||||
viewModel.hide()
|
||||
lifecycleOwner.lifecycleScope.launch {
|
||||
val result = snackbarHostState.showSnackbar(
|
||||
message = context.getString(R.string.msg_item_hidden, item.label),
|
||||
actionLabel = context.getString(R.string.action_undo),
|
||||
|
||||
)
|
||||
if(result == SnackbarResult.ActionPerformed) {
|
||||
viewModel.unhide()
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
it == DismissValue.DismissedToStart
|
||||
|
||||
@ -12,6 +12,7 @@ import androidx.compose.material.icons.Icons
|
||||
import androidx.compose.material.icons.rounded.*
|
||||
import androidx.compose.material3.Icon
|
||||
import androidx.compose.material3.MaterialTheme
|
||||
import androidx.compose.material3.SnackbarResult
|
||||
import androidx.compose.material3.Text
|
||||
import androidx.compose.runtime.Composable
|
||||
import androidx.compose.runtime.collectAsState
|
||||
@ -22,10 +23,12 @@ import androidx.compose.ui.Modifier
|
||||
import androidx.compose.ui.geometry.Rect
|
||||
import androidx.compose.ui.graphics.TransformOrigin
|
||||
import androidx.compose.ui.platform.LocalContext
|
||||
import androidx.compose.ui.platform.LocalLifecycleOwner
|
||||
import androidx.compose.ui.res.stringResource
|
||||
import androidx.compose.ui.text.style.TextOverflow
|
||||
import androidx.compose.ui.unit.ExperimentalUnitApi
|
||||
import androidx.compose.ui.unit.dp
|
||||
import androidx.lifecycle.lifecycleScope
|
||||
import de.mm20.launcher2.search.data.Contact
|
||||
import de.mm20.launcher2.ui.R
|
||||
import de.mm20.launcher2.ui.animation.animateTextStyleAsState
|
||||
@ -36,7 +39,9 @@ import de.mm20.launcher2.ui.ktx.toDp
|
||||
import de.mm20.launcher2.ui.ktx.toPixels
|
||||
import de.mm20.launcher2.ui.locals.LocalFavoritesEnabled
|
||||
import de.mm20.launcher2.ui.locals.LocalGridIconSize
|
||||
import de.mm20.launcher2.ui.locals.LocalSnackbarHostState
|
||||
import de.mm20.launcher2.ui.modifier.scale
|
||||
import kotlinx.coroutines.launch
|
||||
|
||||
@OptIn(ExperimentalUnitApi::class)
|
||||
@Composable
|
||||
@ -49,6 +54,9 @@ fun ContactItem(
|
||||
val context = LocalContext.current
|
||||
val viewModel = remember(contact) { ContactItemVM(contact) }
|
||||
|
||||
val lifecycleOwner = LocalLifecycleOwner.current
|
||||
val snackbarHostState = LocalSnackbarHostState.current
|
||||
|
||||
val transition = updateTransition(showDetails, label = "ContactItem")
|
||||
|
||||
Column(
|
||||
@ -257,6 +265,16 @@ fun ContactItem(
|
||||
action = {
|
||||
viewModel.hide()
|
||||
onBack()
|
||||
lifecycleOwner.lifecycleScope.launch {
|
||||
val result = snackbarHostState.showSnackbar(
|
||||
message = context.getString(R.string.msg_item_hidden, contact.label),
|
||||
actionLabel = context.getString(R.string.action_undo),
|
||||
|
||||
)
|
||||
if(result == SnackbarResult.ActionPerformed) {
|
||||
viewModel.unhide()
|
||||
}
|
||||
}
|
||||
})
|
||||
}
|
||||
toolbarActions.add(hideAction)
|
||||
|
||||
@ -8,20 +8,19 @@ import androidx.compose.animation.core.updateTransition
|
||||
import androidx.compose.foundation.layout.*
|
||||
import androidx.compose.material.icons.Icons
|
||||
import androidx.compose.material.icons.rounded.*
|
||||
import androidx.compose.material3.AlertDialog
|
||||
import androidx.compose.material3.MaterialTheme
|
||||
import androidx.compose.material3.Text
|
||||
import androidx.compose.material3.TextButton
|
||||
import androidx.compose.material3.*
|
||||
import androidx.compose.runtime.*
|
||||
import androidx.compose.ui.Alignment
|
||||
import androidx.compose.ui.Modifier
|
||||
import androidx.compose.ui.geometry.Rect
|
||||
import androidx.compose.ui.graphics.TransformOrigin
|
||||
import androidx.compose.ui.platform.LocalContext
|
||||
import androidx.compose.ui.platform.LocalLifecycleOwner
|
||||
import androidx.compose.ui.res.stringResource
|
||||
import androidx.compose.ui.text.style.TextOverflow
|
||||
import androidx.compose.ui.unit.ExperimentalUnitApi
|
||||
import androidx.compose.ui.unit.dp
|
||||
import androidx.lifecycle.lifecycleScope
|
||||
import de.mm20.launcher2.search.data.File
|
||||
import de.mm20.launcher2.ui.R
|
||||
import de.mm20.launcher2.ui.animation.animateTextStyleAsState
|
||||
@ -33,7 +32,9 @@ import de.mm20.launcher2.ui.ktx.toDp
|
||||
import de.mm20.launcher2.ui.ktx.toPixels
|
||||
import de.mm20.launcher2.ui.locals.LocalFavoritesEnabled
|
||||
import de.mm20.launcher2.ui.locals.LocalGridIconSize
|
||||
import de.mm20.launcher2.ui.locals.LocalSnackbarHostState
|
||||
import de.mm20.launcher2.ui.modifier.scale
|
||||
import kotlinx.coroutines.launch
|
||||
import java.text.DecimalFormat
|
||||
import kotlin.math.roundToInt
|
||||
|
||||
@ -48,6 +49,9 @@ fun FileItem(
|
||||
val context = LocalContext.current
|
||||
val viewModel = remember(file.key) { FileItemVM(file) }
|
||||
|
||||
val lifecycleOwner = LocalLifecycleOwner.current
|
||||
val snackbarHostState = LocalSnackbarHostState.current
|
||||
|
||||
val transition = updateTransition(showDetails, label = "ContactItem")
|
||||
|
||||
Column(
|
||||
@ -235,6 +239,17 @@ fun FileItem(
|
||||
action = {
|
||||
viewModel.hide()
|
||||
onBack()
|
||||
lifecycleOwner.lifecycleScope.launch {
|
||||
val result = snackbarHostState.showSnackbar(
|
||||
message = context.getString(R.string.msg_item_hidden, file.label),
|
||||
actionLabel = context.getString(R.string.action_undo),
|
||||
|
||||
)
|
||||
if(result == SnackbarResult.ActionPerformed) {
|
||||
viewModel.unhide()
|
||||
}
|
||||
}
|
||||
|
||||
})
|
||||
}
|
||||
toolbarActions.add(hideAction)
|
||||
|
||||
@ -8,6 +8,7 @@ import androidx.compose.material.ExperimentalMaterialApi
|
||||
import androidx.compose.material.icons.Icons
|
||||
import androidx.compose.material.icons.rounded.*
|
||||
import androidx.compose.material3.MaterialTheme
|
||||
import androidx.compose.material3.SnackbarResult
|
||||
import androidx.compose.material3.Text
|
||||
import androidx.compose.runtime.Composable
|
||||
import androidx.compose.runtime.collectAsState
|
||||
@ -17,9 +18,11 @@ import androidx.compose.ui.Modifier
|
||||
import androidx.compose.ui.geometry.Rect
|
||||
import androidx.compose.ui.graphics.TransformOrigin
|
||||
import androidx.compose.ui.platform.LocalContext
|
||||
import androidx.compose.ui.platform.LocalLifecycleOwner
|
||||
import androidx.compose.ui.res.stringResource
|
||||
import androidx.compose.ui.text.style.TextOverflow
|
||||
import androidx.compose.ui.unit.dp
|
||||
import androidx.lifecycle.lifecycleScope
|
||||
import de.mm20.launcher2.search.data.AppShortcut
|
||||
import de.mm20.launcher2.ui.R
|
||||
import de.mm20.launcher2.ui.animation.animateTextStyleAsState
|
||||
@ -31,7 +34,9 @@ import de.mm20.launcher2.ui.ktx.toDp
|
||||
import de.mm20.launcher2.ui.ktx.toPixels
|
||||
import de.mm20.launcher2.ui.locals.LocalFavoritesEnabled
|
||||
import de.mm20.launcher2.ui.locals.LocalGridIconSize
|
||||
import de.mm20.launcher2.ui.locals.LocalSnackbarHostState
|
||||
import de.mm20.launcher2.ui.modifier.scale
|
||||
import kotlinx.coroutines.launch
|
||||
import kotlin.math.pow
|
||||
import kotlin.math.roundToInt
|
||||
|
||||
@ -46,6 +51,9 @@ fun AppShortcutItem(
|
||||
val viewModel = remember { ShortcutItemVM(shortcut) }
|
||||
val context = LocalContext.current
|
||||
|
||||
val lifecycleOwner = LocalLifecycleOwner.current
|
||||
val snackbarHostState = LocalSnackbarHostState.current
|
||||
|
||||
val transition = updateTransition(showDetails, label = "AppShortcutItem")
|
||||
|
||||
Column(
|
||||
@ -143,6 +151,17 @@ fun AppShortcutItem(
|
||||
action = {
|
||||
viewModel.hide()
|
||||
onBack()
|
||||
|
||||
lifecycleOwner.lifecycleScope.launch {
|
||||
val result = snackbarHostState.showSnackbar(
|
||||
message = context.getString(R.string.msg_item_hidden, shortcut.label),
|
||||
actionLabel = context.getString(R.string.action_undo),
|
||||
|
||||
)
|
||||
if(result == SnackbarResult.ActionPerformed) {
|
||||
viewModel.unhide()
|
||||
}
|
||||
}
|
||||
})
|
||||
}
|
||||
toolbarActions.add(hideAction)
|
||||
|
||||
@ -1,6 +1,7 @@
|
||||
package de.mm20.launcher2.ui.locals
|
||||
|
||||
import android.appwidget.AppWidgetHost
|
||||
import androidx.compose.material3.SnackbarHostState
|
||||
import androidx.compose.runtime.compositionLocalOf
|
||||
import androidx.compose.ui.geometry.Size
|
||||
import androidx.compose.ui.platform.LocalContext
|
||||
@ -22,6 +23,8 @@ val LocalGridColumns = compositionLocalOf { 5 }
|
||||
|
||||
val LocalGridIconSize = compositionLocalOf { 48.dp }
|
||||
|
||||
val LocalSnackbarHostState = compositionLocalOf { SnackbarHostState() }
|
||||
|
||||
/**
|
||||
* Workaround a bug in Jetpack Compose which incorrectly places popups
|
||||
* that are nested inside other popups.
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user