Skip to content

Commit

Permalink
Support alerts on the bottom of the screen
Browse files Browse the repository at this point in the history
  • Loading branch information
wingio committed Sep 22, 2023
1 parent 7c020ed commit 6eddf2a
Show file tree
Hide file tree
Showing 8 changed files with 70 additions and 21 deletions.
14 changes: 13 additions & 1 deletion app/src/main/java/com/materiiapps/gloom/ui/GloomActivity.kt
Original file line number Diff line number Diff line change
Expand Up @@ -7,9 +7,12 @@ import androidx.activity.ComponentActivity
import androidx.activity.compose.setContent
import androidx.compose.foundation.isSystemInDarkTheme
import androidx.compose.runtime.CompositionLocalProvider
import androidx.compose.runtime.LaunchedEffect
import androidx.compose.runtime.SideEffect
import androidx.compose.ui.graphics.Color
import androidx.compose.ui.platform.LocalContext
import androidx.compose.ui.unit.IntOffset
import androidx.compose.ui.unit.dp
import androidx.core.splashscreen.SplashScreen.Companion.installSplashScreen
import androidx.core.view.WindowCompat
import cafe.adriel.voyager.navigator.Navigator
Expand All @@ -22,6 +25,7 @@ import com.materiiapps.gloom.ui.screens.auth.LandingScreen
import com.materiiapps.gloom.ui.screens.root.RootScreen
import com.materiiapps.gloom.ui.theme.GloomTheme
import com.materiiapps.gloom.ui.transitions.SlideTransition
import com.materiiapps.gloom.ui.utils.toPx
import com.materiiapps.gloom.ui.viewmodels.main.MainViewModel
import com.materiiapps.gloom.ui.widgets.alerts.AlertHost
import com.materiiapps.gloom.utils.LinkHandler
Expand Down Expand Up @@ -59,6 +63,7 @@ class GloomActivity : ComponentActivity() {

GloomTheme(isDark, prefs.monet) {
val systemUiController = rememberSystemUiController()
val navNarOffset = -((80 + 24).dp.toPx())
val defaultScreen = if (auth.isSignedIn)
RootScreen()
else
Expand All @@ -75,14 +80,21 @@ class GloomActivity : ComponentActivity() {
}

DeepLinkWrapper { handler ->
AlertHost {
AlertHost { alertController ->
Navigator(
screen = defaultScreen,
disposeBehavior = NavigatorDisposeBehavior(
disposeNestedNavigators = false,
disposeSteps = true
)
) {
LaunchedEffect(it.lastItem) {
if(it.lastItem is RootScreen)
alertController.currentOffset = IntOffset(0, navNarOffset)
else
alertController.currentOffset = IntOffset.Zero
}

CompositionLocalProvider(
LocalLinkHandler provides LinkHandler(LocalContext.current)
) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -51,6 +51,9 @@ class AlertTestingScreen : Screen {
var duration by remember {
mutableStateOf(Alert.Duration.SHORT)
}
var position by remember {
mutableStateOf(Alert.Position.TOP)
}

Scaffold(
topBar = { Toolbar(scrollBehavior) },
Expand Down Expand Up @@ -103,14 +106,21 @@ class AlertTestingScreen : Screen {
onPrefChange = { duration = it }
)

SettingsItemChoice(
label = "Position",
pref = position,
onPrefChange = { position = it }
)

SettingsButton(
label = stringResource(Res.strings.dev_alert_action_show_alert),
onClick = {
alertController.showAlert(
title = title.ifBlank { null },
message = message.ifBlank { null },
icon = if (showIcon) Icons.Outlined.Info else null,
duration = duration
duration = duration,
position = position
)
}
)
Expand All @@ -124,7 +134,8 @@ class AlertTestingScreen : Screen {
title = title.ifBlank { null },
message = message.ifBlank { null },
icon = if (showIcon) Icons.Outlined.Info else null,
duration = duration
duration = duration,
position = position
)
}
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -4,11 +4,17 @@ import androidx.compose.foundation.layout.WindowInsets
import androidx.compose.foundation.layout.asPaddingValues
import androidx.compose.foundation.layout.systemBars
import androidx.compose.runtime.Composable
import androidx.compose.ui.platform.LocalDensity
import androidx.compose.ui.unit.Dp

object DimenUtils {

val navBarPadding: Dp
@Composable get() = WindowInsets.systemBars.asPaddingValues().calculateBottomPadding()

}

@Composable
fun Dp.toPx() = with(LocalDensity.current) {
toPx().toInt()
}
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@ import androidx.compose.foundation.layout.Column
import androidx.compose.foundation.layout.Row
import androidx.compose.foundation.layout.fillMaxWidth
import androidx.compose.foundation.layout.padding
import androidx.compose.material3.CardDefaults
import androidx.compose.material3.ElevatedCard
import androidx.compose.material3.Icon
import androidx.compose.material3.LocalContentColor
Expand All @@ -27,6 +28,7 @@ fun AlertCard(
modifier: Modifier = Modifier
) {
ElevatedCard(
elevation = CardDefaults.elevatedCardElevation(10.dp),
modifier = modifier
) {
Row(
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@ import androidx.compose.runtime.mutableStateOf
import androidx.compose.runtime.setValue
import androidx.compose.runtime.staticCompositionLocalOf
import androidx.compose.ui.graphics.vector.ImageVector
import androidx.compose.ui.unit.IntOffset
import com.benasher44.uuid.Uuid
import com.benasher44.uuid.uuid4
import kotlinx.coroutines.CoroutineScope
Expand All @@ -25,14 +26,17 @@ class AlertController(coroutineScope: CoroutineScope = CoroutineScope(Dispatcher
var displayedAlert by mutableStateOf<Alert?>(null)
private set

fun showText(text: String) = showAlert(title = text, icon = Icons.Outlined.Info)
var currentOffset by mutableStateOf<IntOffset>(IntOffset.Zero)

fun showText(text: String) = showAlert(title = text, icon = Icons.Outlined.Info, position = Alert.Position.BOTTOM)

fun showAlert(
title: String? = null,
message: String? = null,
icon: ImageVector? = null,
iconContentDescription: String? = null,
duration: Alert.Duration = Alert.Duration.SHORT,
position: Alert.Position = Alert.Position.TOP,
onClick: (() -> Unit)? = null,
) {
val alert = Alert(
Expand All @@ -41,6 +45,7 @@ class AlertController(coroutineScope: CoroutineScope = CoroutineScope(Dispatcher
icon = icon,
iconContentDescription = iconContentDescription,
duration = duration,
position = position,
onClick = onClick
)

Expand Down Expand Up @@ -77,6 +82,7 @@ data class Alert(
val icon: ImageVector? = null,
val iconContentDescription: String? = null,
val duration: Duration = Duration.SHORT,
val position: Position = Position.TOP,
val onClick: (() -> Unit)? = null,
val id: Uuid = uuid4()
) {
Expand All @@ -88,4 +94,10 @@ data class Alert(
LONG(millis = 10_000)
}

@Stable
enum class Position {
TOP,
BOTTOM
}

}
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,7 @@ import kotlinx.coroutines.delay

@Composable
fun AlertHost(
content: @Composable () -> Unit
content: @Composable (AlertController) -> Unit
) {
val controller = remember { AlertController() }

Expand All @@ -24,7 +24,7 @@ fun AlertHost(
CompositionLocalProvider(
LocalAlertController provides controller
) {
content()
content(controller)
}

val currentAlert = controller.displayedAlert
Expand All @@ -46,8 +46,10 @@ fun AlertHost(
message = currentAlert?.message,
icon = currentAlert?.icon,
iconContentDescription = currentAlert?.iconContentDescription,
position = currentAlert?.position ?: Alert.Position.TOP,
onClick = currentAlert?.onClick,
key = id,
offset = controller.currentOffset,
onDismissed = {
controller.processQueue()
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@ import androidx.compose.animation.slideOutVertically
import androidx.compose.foundation.gestures.Orientation
import androidx.compose.foundation.gestures.draggable
import androidx.compose.foundation.gestures.rememberDraggableState
import androidx.compose.foundation.layout.Box
import androidx.compose.foundation.layout.Column
import androidx.compose.foundation.layout.fillMaxWidth
import androidx.compose.foundation.layout.offset
import androidx.compose.foundation.layout.padding
Expand Down Expand Up @@ -39,16 +39,19 @@ fun AlertPopup(
message: String?,
icon: ImageVector?,
iconContentDescription: String?,
position: Alert.Position = Alert.Position.TOP,
onClick: (() -> Unit)?,
onDismissed: () -> Unit,
key: String?,
alignment: Alignment = Alignment.TopCenter,
offset: IntOffset
) {
val coroutineScope = rememberCoroutineScope()
val posRemembered = remember(key) { position }
val animSpring = spring(
stiffness = Spring.StiffnessMediumLow,
visibilityThreshold = IntOffset.VisibilityThreshold
)

val expandedState = remember {
MutableTransitionState(false)
}
Expand All @@ -58,21 +61,20 @@ fun AlertPopup(
val draggableState = rememberDraggableState {
y += it
}

LaunchedEffect(visible) {
expandedState.targetState = visible
}

val (enterAnimation, exitAnimation) = remember(alignment) {
when (alignment) {
Alignment.TopCenter -> slideInVertically(animSpring) { -it } to slideOutVertically(
val (enterAnimation, exitAnimation) = remember(key) {
when (posRemembered) {
Alert.Position.TOP -> slideInVertically(animSpring) { -it } to slideOutVertically(
animSpring
) { -it }

else -> slideInVertically(animSpring) to slideOutVertically(animSpring)
Alert.Position.BOTTOM -> slideInVertically(animSpring) { it } to slideOutVertically(animSpring) { it }
}
}

LaunchedEffect(visible) {
expandedState.targetState = visible
}

fun animateYTo(pos: Float, onFinished: () -> Unit = {}) {
coroutineScope.launch {
animate(y, pos) { target, _ ->
Expand All @@ -83,14 +85,15 @@ fun AlertPopup(

if (expandedState.currentState || expandedState.targetState || !expandedState.isIdle) {
Popup(
alignment = alignment
alignment = if (posRemembered == Alert.Position.TOP) Alignment.TopCenter else Alignment.BottomCenter,
offset = if(posRemembered == Alert.Position.BOTTOM) offset else IntOffset.Zero
) {
AnimatedVisibility(
visibleState = expandedState,
enter = enterAnimation,
exit = exitAnimation
) {
Box(
Column(
modifier = Modifier
.padding(16.dp)
.fillMaxWidth()
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -34,6 +34,7 @@ import com.materiiapps.gloom.gql.fragment.Contributions
import com.materiiapps.gloom.gql.type.ContributionLevel
import com.materiiapps.gloom.ui.utils.format
import com.materiiapps.gloom.ui.utils.getPluralString
import com.materiiapps.gloom.ui.widgets.alerts.LocalAlertController
import dev.icerock.moko.resources.compose.stringResource
import org.koin.androidx.compose.get

Expand All @@ -42,7 +43,7 @@ fun ContributionGraph(
calendar: Contributions.ContributionCalendar,
spacing: Dp = 5.dp
) {
val toastManager: ToastManager = get()
val alertController = LocalAlertController.current
val lazyListState =
rememberLazyListState(initialFirstVisibleItemIndex = calendar.weeks.lastIndex)

Expand Down Expand Up @@ -76,7 +77,7 @@ fun ContributionGraph(
DayTile(
level = day.contributionLevel,
onClick = {
toastManager.showToast(
alertController.showText(
getPluralString(
Res.plurals.contributions_toast,
day.contributionCount,
Expand Down

0 comments on commit 6eddf2a

Please sign in to comment.