From a985e8d0fc7eda2e48318d8c0f515d3ce274988e Mon Sep 17 00:00:00 2001 From: Nishant Mishra Date: Mon, 27 Oct 2025 20:27:09 +0530 Subject: [PATCH] fix(billing): adapt UI according to plus status --- .../billing/TomatoPlusPaywallDialog.kt | 57 +++++++++++++ .../java/org/nsh07/pomodoro/ui/AppScreen.kt | 1 + .../ui/settingsScreen/SettingsScreen.kt | 49 ++--------- .../ui/settingsScreen/components/AboutCard.kt | 8 +- .../ui/settingsScreen/components/PlusPromo.kt | 82 +++++++++++++++++++ .../pomodoro/ui/timerScreen/TimerScreen.kt | 5 +- 6 files changed, 159 insertions(+), 43 deletions(-) create mode 100644 app/src/main/java/org/nsh07/pomodoro/ui/settingsScreen/components/PlusPromo.kt diff --git a/app/src/foss/java/org/nsh07/pomodoro/billing/TomatoPlusPaywallDialog.kt b/app/src/foss/java/org/nsh07/pomodoro/billing/TomatoPlusPaywallDialog.kt index 973041c..e406f57 100644 --- a/app/src/foss/java/org/nsh07/pomodoro/billing/TomatoPlusPaywallDialog.kt +++ b/app/src/foss/java/org/nsh07/pomodoro/billing/TomatoPlusPaywallDialog.kt @@ -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") + } + } + } } \ No newline at end of file diff --git a/app/src/main/java/org/nsh07/pomodoro/ui/AppScreen.kt b/app/src/main/java/org/nsh07/pomodoro/ui/AppScreen.kt index b7cab88..16a539b 100644 --- a/app/src/main/java/org/nsh07/pomodoro/ui/AppScreen.kt +++ b/app/src/main/java/org/nsh07/pomodoro/ui/AppScreen.kt @@ -164,6 +164,7 @@ fun AppScreen( entry { TimerScreen( timerState = uiState, + isPlus = isPlus, progress = { progress }, onAction = { action -> when (action) { diff --git a/app/src/main/java/org/nsh07/pomodoro/ui/settingsScreen/SettingsScreen.kt b/app/src/main/java/org/nsh07/pomodoro/ui/settingsScreen/SettingsScreen.kt index 00b2de8..af64b04 100644 --- a/app/src/main/java/org/nsh07/pomodoro/ui/settingsScreen/SettingsScreen.kt +++ b/app/src/main/java/org/nsh07/pomodoro/ui/settingsScreen/SettingsScreen.kt @@ -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 = { diff --git a/app/src/main/java/org/nsh07/pomodoro/ui/settingsScreen/components/AboutCard.kt b/app/src/main/java/org/nsh07/pomodoro/ui/settingsScreen/components/AboutCard.kt index 3bf2f6c..1f85c76 100644 --- a/app/src/main/java/org/nsh07/pomodoro/ui/settingsScreen/components/AboutCard.kt +++ b/app/src/main/java/org/nsh07/pomodoro/ui/settingsScreen/components/AboutCard.kt @@ -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 ) diff --git a/app/src/main/java/org/nsh07/pomodoro/ui/settingsScreen/components/PlusPromo.kt b/app/src/main/java/org/nsh07/pomodoro/ui/settingsScreen/components/PlusPromo.kt new file mode 100644 index 0000000..858dbdb --- /dev/null +++ b/app/src/main/java/org/nsh07/pomodoro/ui/settingsScreen/components/PlusPromo.kt @@ -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 . + */ + +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 + ) + } +} \ No newline at end of file diff --git a/app/src/main/java/org/nsh07/pomodoro/ui/timerScreen/TimerScreen.kt b/app/src/main/java/org/nsh07/pomodoro/ui/timerScreen/TimerScreen.kt index ee77820..a1a44f4 100644 --- a/app/src/main/java/org/nsh07/pomodoro/ui/timerScreen/TimerScreen.kt +++ b/app/src/main/java/org/nsh07/pomodoro/ui/timerScreen/TimerScreen.kt @@ -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 }, {} )