fix(billing): adapt UI according to plus status

This commit is contained in:
Nishant Mishra
2025-10-27 20:27:09 +05:30
parent 540b941b23
commit a985e8d0fc
6 changed files with 159 additions and 43 deletions

View File

@@ -17,11 +17,68 @@
package org.nsh07.pomodoro.billing
import androidx.activity.compose.BackHandler
import androidx.compose.foundation.background
import androidx.compose.foundation.layout.Box
import androidx.compose.foundation.layout.Column
import androidx.compose.foundation.layout.Spacer
import androidx.compose.foundation.layout.fillMaxSize
import androidx.compose.foundation.layout.height
import androidx.compose.foundation.layout.padding
import androidx.compose.material3.Button
import androidx.compose.material3.Icon
import androidx.compose.material3.MaterialTheme.colorScheme
import androidx.compose.material3.MaterialTheme.typography
import androidx.compose.material3.Text
import androidx.compose.runtime.Composable
import androidx.compose.ui.Alignment
import androidx.compose.ui.Modifier
import androidx.compose.ui.platform.LocalUriHandler
import androidx.compose.ui.res.painterResource
import androidx.compose.ui.text.style.TextAlign
import androidx.compose.ui.unit.dp
import org.nsh07.pomodoro.R
import org.nsh07.pomodoro.ui.theme.AppFonts.robotoFlexTopBar
@Composable
fun TomatoPlusPaywallDialog(
isPlus: Boolean,
onDismiss: () -> Unit
) {
val uriHandler = LocalUriHandler.current
BackHandler(enabled = true, onDismiss)
Box(
contentAlignment = Alignment.Center,
modifier = Modifier
.fillMaxSize()
.background(colorScheme.surface)
) {
Column(horizontalAlignment = Alignment.CenterHorizontally) {
Icon(
painterResource(R.drawable.bmc),
null,
tint = colorScheme.onSurface
)
Spacer(Modifier.height(16.dp))
Text(
"Tomato FOSS",
style = typography.headlineSmall,
fontFamily = robotoFlexTopBar,
color = colorScheme.onSurface
)
Spacer(Modifier.height(8.dp))
Text(
"All features are unlocked in this version. If my app made a difference in your life, please consider supporting me by donating on ${"BuyMeACoffee"}.",
textAlign = TextAlign.Center,
color = colorScheme.onSurfaceVariant,
modifier = Modifier.padding(horizontal = 24.dp)
)
Spacer(Modifier.height(16.dp))
Button(onClick = { uriHandler.openUri("https://coff.ee/nsh07") }) {
Text("Buy Me A Coffee")
}
}
}
}

View File

@@ -164,6 +164,7 @@ fun AppScreen(
entry<Screen.Timer> {
TimerScreen(
timerState = uiState,
isPlus = isPlus,
progress = { progress },
onAction = { action ->
when (action) {

View File

@@ -26,26 +26,19 @@ import androidx.compose.animation.slideInHorizontally
import androidx.compose.animation.slideOutHorizontally
import androidx.compose.animation.togetherWith
import androidx.compose.foundation.background
import androidx.compose.foundation.clickable
import androidx.compose.foundation.layout.Arrangement
import androidx.compose.foundation.layout.Column
import androidx.compose.foundation.layout.Row
import androidx.compose.foundation.layout.Spacer
import androidx.compose.foundation.layout.fillMaxSize
import androidx.compose.foundation.layout.height
import androidx.compose.foundation.layout.padding
import androidx.compose.foundation.layout.size
import androidx.compose.foundation.layout.width
import androidx.compose.foundation.lazy.LazyColumn
import androidx.compose.foundation.lazy.itemsIndexed
import androidx.compose.foundation.shape.CircleShape
import androidx.compose.foundation.text.input.TextFieldState
import androidx.compose.material3.ExperimentalMaterial3Api
import androidx.compose.material3.ExperimentalMaterial3ExpressiveApi
import androidx.compose.material3.Icon
import androidx.compose.material3.LocalTextStyle
import androidx.compose.material3.MaterialTheme.colorScheme
import androidx.compose.material3.MaterialTheme.typography
import androidx.compose.material3.SliderState
import androidx.compose.material3.Text
import androidx.compose.material3.TopAppBar
@@ -58,7 +51,6 @@ import androidx.compose.runtime.saveable.rememberSaveable
import androidx.compose.runtime.snapshots.SnapshotStateList
import androidx.compose.ui.Alignment
import androidx.compose.ui.Modifier
import androidx.compose.ui.draw.clip
import androidx.compose.ui.graphics.Color
import androidx.compose.ui.input.nestedscroll.nestedScroll
import androidx.compose.ui.platform.LocalContext
@@ -76,6 +68,7 @@ import org.nsh07.pomodoro.service.TimerService
import org.nsh07.pomodoro.ui.Screen
import org.nsh07.pomodoro.ui.settingsScreen.components.AboutCard
import org.nsh07.pomodoro.ui.settingsScreen.components.ClickableListItem
import org.nsh07.pomodoro.ui.settingsScreen.components.PlusPromo
import org.nsh07.pomodoro.ui.settingsScreen.screens.AlarmSettings
import org.nsh07.pomodoro.ui.settingsScreen.screens.AppearanceSettings
import org.nsh07.pomodoro.ui.settingsScreen.screens.TimerSettings
@@ -233,44 +226,20 @@ private fun SettingsScreen(
) {
item { Spacer(Modifier.height(12.dp)) }
item {
Row(
verticalAlignment = Alignment.CenterVertically,
modifier = Modifier
.clip(CircleShape)
.background(colorScheme.primary)
.padding(16.dp)
.clickable { setShowPaywall(true) }
) {
Icon(
painterResource(R.drawable.tomato_logo_notification),
null,
tint = colorScheme.onPrimary,
modifier = Modifier
.size(24.dp)
)
Spacer(Modifier.width(8.dp))
Text(
if (!isPlus) stringResource(R.string.get_plus)
else stringResource(R.string.app_name_plus),
style = typography.titleLarge,
fontFamily = robotoFlexTopBar,
color = colorScheme.onPrimary
)
Spacer(Modifier.weight(1f))
Icon(
painterResource(R.drawable.arrow_forward_big),
null,
tint = colorScheme.onPrimary
)
}
if (!isPlus) item {
PlusPromo(isPlus, setShowPaywall)
Spacer(Modifier.height(14.dp))
}
item { AboutCard() }
item { AboutCard(isPlus) }
item { Spacer(Modifier.height(12.dp)) }
if (isPlus) item {
PlusPromo(isPlus, setShowPaywall)
Spacer(Modifier.height(14.dp))
}
itemsIndexed(settingsScreens) { index, item ->
ClickableListItem(
leadingContent = {

View File

@@ -51,7 +51,10 @@ import org.nsh07.pomodoro.ui.theme.AppFonts.robotoFlexTopBar
// Taken from https://github.com/shub39/Grit/blob/master/app/src/main/java/com/shub39/grit/core/presentation/settings/ui/component/AboutApp.kt
@Composable
fun AboutCard(modifier: Modifier = Modifier) {
fun AboutCard(
isPlus: Boolean,
modifier: Modifier = Modifier
) {
val uriHandler = LocalUriHandler.current
val context = LocalContext.current
@@ -77,7 +80,8 @@ fun AboutCard(modifier: Modifier = Modifier) {
) {
Column {
Text(
text = stringResource(R.string.app_name),
if (!isPlus) stringResource(R.string.app_name)
else stringResource(R.string.app_name_plus),
style = MaterialTheme.typography.titleLarge,
fontFamily = robotoFlexTopBar
)

View File

@@ -0,0 +1,82 @@
/*
* Copyright (c) 2025 Nishant Mishra
*
* This file is part of Tomato - a minimalist pomodoro timer for Android.
*
* Tomato is free software: you can redistribute it and/or modify it under the terms of the GNU
* General Public License as published by the Free Software Foundation, either version 3 of the
* License, or (at your option) any later version.
*
* Tomato is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even
* the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General
* Public License for more details.
*
* You should have received a copy of the GNU General Public License along with Tomato.
* If not, see <https://www.gnu.org/licenses/>.
*/
package org.nsh07.pomodoro.ui.settingsScreen.components
import androidx.compose.foundation.background
import androidx.compose.foundation.clickable
import androidx.compose.foundation.layout.Row
import androidx.compose.foundation.layout.Spacer
import androidx.compose.foundation.layout.padding
import androidx.compose.foundation.layout.size
import androidx.compose.foundation.layout.width
import androidx.compose.foundation.shape.CircleShape
import androidx.compose.material3.Icon
import androidx.compose.material3.MaterialTheme.colorScheme
import androidx.compose.material3.MaterialTheme.typography
import androidx.compose.material3.Text
import androidx.compose.runtime.Composable
import androidx.compose.ui.Alignment
import androidx.compose.ui.Modifier
import androidx.compose.ui.draw.clip
import androidx.compose.ui.res.painterResource
import androidx.compose.ui.res.stringResource
import androidx.compose.ui.unit.dp
import org.nsh07.pomodoro.R
import org.nsh07.pomodoro.ui.theme.AppFonts.robotoFlexTopBar
@Composable
fun PlusPromo(
isPlus: Boolean,
setShowPaywall: (Boolean) -> Unit,
modifier: Modifier = Modifier
) {
val container = if (isPlus) colorScheme.surfaceBright else colorScheme.primary
val onContainer = if (isPlus) colorScheme.onSurface else colorScheme.onPrimary
val onContainerVariant = if (isPlus) colorScheme.onSurfaceVariant else colorScheme.onPrimary
Row(
verticalAlignment = Alignment.CenterVertically,
modifier = modifier
.clip(CircleShape)
.background(container)
.padding(16.dp)
.clickable { setShowPaywall(true) }
) {
Icon(
painterResource(R.drawable.tomato_logo_notification),
null,
tint = onContainerVariant,
modifier = Modifier
.size(24.dp)
)
Spacer(Modifier.width(8.dp))
Text(
if (!isPlus) stringResource(R.string.get_plus)
else stringResource(R.string.app_name_plus),
style = typography.titleLarge,
fontFamily = robotoFlexTopBar,
color = onContainer
)
Spacer(Modifier.weight(1f))
Icon(
painterResource(R.drawable.arrow_forward_big),
null,
tint = onContainerVariant
)
}
}

View File

@@ -107,6 +107,7 @@ import org.nsh07.pomodoro.ui.timerScreen.viewModel.TimerState
@Composable
fun SharedTransitionScope.TimerScreen(
timerState: TimerState,
isPlus: Boolean,
progress: () -> Float,
onAction: (TimerAction) -> Unit,
modifier: Modifier = Modifier
@@ -159,7 +160,8 @@ fun SharedTransitionScope.TimerScreen(
when (it) {
TimerMode.BRAND ->
Text(
stringResource(R.string.app_name),
if (!isPlus) stringResource(R.string.app_name)
else stringResource(R.string.app_name_plus),
style = TextStyle(
fontFamily = robotoFlexTopBar,
fontSize = 32.sp,
@@ -552,6 +554,7 @@ fun TimerScreenPreview() {
SharedTransitionLayout {
TimerScreen(
timerState,
isPlus = true,
{ 0.3f },
{}
)