From 5f6dbfa76fd0349771c565572585a8d7f2f4c8ca Mon Sep 17 00:00:00 2001 From: Nishant Mishra Date: Fri, 24 Oct 2025 19:24:08 +0530 Subject: [PATCH 01/25] chore(docs): update API version in README --- README.md | 19 ++++++++++++++----- 1 file changed, 14 insertions(+), 5 deletions(-) diff --git a/README.md b/README.md index 1562443..d534ff2 100644 --- a/README.md +++ b/README.md @@ -8,7 +8,13 @@ Tomato is a minimalist Pomodoro timer for Android based on Material 3 Expressive > [!NOTE] -> Tomato is available on Google Play in closed testing. Please [use this link to join the testers Google Group](https://groups.google.com/g/nsh07-app-testers) and then install [Tomato from the Play Store with this link](https://play.google.com/store/apps/details?id=org.nsh07.pomodoro). Tomato needs 12 testers for at least 14 days for the app to be available on Google Play publicly. +> Tomato is available on Google Play in closed testing. +> +Please [use this link to join the testers Google Group](https://groups.google.com/g/nsh07-app-testers) +> and then +> +install [Tomato from the Play Store with this link](https://play.google.com/store/apps/details?id=org.nsh07.pomodoro). +> Tomato needs 12 testers for at least 14 days for the app to be available on Google Play publicly.
@@ -24,7 +30,7 @@ Tomato is a minimalist Pomodoro timer for Android based on Material 3 Expressive - +

@@ -48,9 +54,11 @@ Tomato is a minimalist Pomodoro timer for Android based on Material 3 Expressive
-> *"... an app to support this habit helps me stay focused and get things done. Currently, that app is Tomato."* +> *"... an app to support this habit helps me stay focused and get things done. Currently, that app +is Tomato."* -\- [*Android Authority*](https://www.androidauthority.com/best-new-android-apps-october-2025-3602966/) +\- [*Android +Authority*](https://www.androidauthority.com/best-new-android-apps-october-2025-3602966/)
@@ -94,7 +102,8 @@ translating this project into languages you know. - **Google Play Store** (recommended): Tomato is available for closed testing on Google Play. Use [this link to join the testers Google Group](https://groups.google.com/g/nsh07-app-testers), then - [install Tomato from the Play Store with this link](https://play.google.com/store/apps/details?id=org.nsh07.pomodoro) and help Tomato to get an official Play Store release. + [install Tomato from the Play Store with this link](https://play.google.com/store/apps/details?id=org.nsh07.pomodoro) + and help Tomato to get an official Play Store release. - **F-Droid** (recommended): Tomato is available on the official F-Droid repository. Simply open your preferred F-Droid app and search for Tomato. Updates on F-Droid are generally a week late. To get faster updates, you can install it through From e1219f77b79085d383a0b9b6547d6513a6860cbd Mon Sep 17 00:00:00 2001 From: Nishant Mishra Date: Fri, 24 Oct 2025 20:33:17 +0530 Subject: [PATCH 02/25] fix: update play store icon --- app/src/main/res/drawable/play_store.xml | 27 +++++++++++++++++++----- 1 file changed, 22 insertions(+), 5 deletions(-) diff --git a/app/src/main/res/drawable/play_store.xml b/app/src/main/res/drawable/play_store.xml index fc7ef76..51103b7 100644 --- a/app/src/main/res/drawable/play_store.xml +++ b/app/src/main/res/drawable/play_store.xml @@ -1,10 +1,27 @@ + + + android:viewportWidth="24" + android:viewportHeight="24"> + android:fillColor="#ffffff" + android:pathData="m12.213,13.862c-0.337,-0.338 -0.884,-0.338 -1.22,0 -0.883,0.884 -6.416,6.433 -7.161,7.175 0.865,0.922 2.431,1.145 3.528,0.475l7.946,-4.554c-0.733,-0.731 -2.349,-2.35 -3.092,-3.096zM10.993,10.2c0.337,0.338 0.884,0.338 1.22,0l1.856,-1.86 -0.002,-0.001L15.33,7.077 7.39,2.505C6.271,1.804 4.658,2.044 3.79,2.984 4.518,3.707 10.125,9.332 10.993,10.2ZM9.775,12.643c0.337,-0.338 0.337,-0.886 0,-1.224L4.805,6.434 3.02,4.652C3.007,4.756 2.998,4.87 3,4.98l0.001,14.069c0.004,0.132 0.023,0.286 0.044,0.418 1.175,-1.151 5.501,-5.573 6.73,-6.825zM19.519,9.489 L16.878,7.968c-0.774,0.768 -2.656,2.66 -3.447,3.452 -0.338,0.338 -0.338,0.886 0,1.224 0.796,0.792 2.645,2.656 3.424,3.428l2.639,-1.512c1.996,-0.99 2.011,-4.063 0.025,-5.071z" + android:strokeWidth="0.599991" /> From 90322bc621a40170d62bf35c556daace0f0fc5d2 Mon Sep 17 00:00:00 2001 From: Hosted Weblate Date: Fri, 24 Oct 2025 21:02:55 +0200 Subject: [PATCH 03/25] Translated using Weblate (Arabic) Currently translated at 96.8% (61 of 63 strings) Translated using Weblate (Chinese (Simplified Han script)) Currently translated at 100.0% (63 of 63 strings) Translated using Weblate (Ukrainian) Currently translated at 100.0% (63 of 63 strings) Translated using Weblate (Hindi) Currently translated at 100.0% (15 of 15 strings) Translated using Weblate (Hindi) Currently translated at 100.0% (63 of 63 strings) Co-authored-by: Clyde Johanson Co-authored-by: Hosted Weblate Co-authored-by: K-MAX Co-authored-by: Nishant Mishra <66912344+nsh07@users.noreply.github.com> Co-authored-by: vintagezero Translate-URL: https://hosted.weblate.org/projects/tomato/store-descriptions/hi/ Translate-URL: https://hosted.weblate.org/projects/tomato/strings/ar/ Translate-URL: https://hosted.weblate.org/projects/tomato/strings/hi/ Translate-URL: https://hosted.weblate.org/projects/tomato/strings/uk/ Translate-URL: https://hosted.weblate.org/projects/tomato/strings/zh_Hans/ Translation: Tomato/Store descriptions Translation: Tomato/Strings --- app/src/main/res/values-ar/strings.xml | 9 ++- app/src/main/res/values-hi/strings.xml | 59 +++++++++++++++++++ app/src/main/res/values-uk/strings.xml | 7 ++- app/src/main/res/values-zh-rCN/strings.xml | 5 +- .../android/hi-IN/full_description.txt | 12 ++++ 5 files changed, 88 insertions(+), 4 deletions(-) create mode 100644 fastlane/metadata/android/hi-IN/full_description.txt diff --git a/app/src/main/res/values-ar/strings.xml b/app/src/main/res/values-ar/strings.xml index 09780a8..23c0782 100644 --- a/app/src/main/res/values-ar/strings.xml +++ b/app/src/main/res/values-ar/strings.xml @@ -19,7 +19,7 @@ ديناميكي لون النظام (الافتراضي) - منبه + المنبه فاتح داكن اختر سمة @@ -31,7 +31,7 @@ التنبيه عند انتهاء المؤقت اهتزاز الاهتزاز عندما ينتهي المؤقت - سمة + السمة الاعدادات طول الجلسة فترات التركيز في الجلسة الواحدة: %1$d @@ -57,4 +57,9 @@ المؤقت تقدم المؤقت السنة الماضية + العرض الدائم علي الشاشة + اضغط في أي مكان أثناء عرض المؤقت للتبديل إلى وضع العرض الدائم على الشاشة + المظهر + الفترات + الصوت diff --git a/app/src/main/res/values-hi/strings.xml b/app/src/main/res/values-hi/strings.xml index 2f3ad16..a9b9992 100644 --- a/app/src/main/res/values-hi/strings.xml +++ b/app/src/main/res/values-hi/strings.xml @@ -3,4 +3,63 @@ प्रारंभ करें विराम करें ध्यान + अलार्म + टाइमर पूरा होने पर अलार्म बजाएँ + अलार्म ध्वनि + ऑलवेज ऑन डिस्प्ले + AOD मोड चालू करने के लिए टाइमर देखते समय कहीं भी टैप करें + काली थीम + पूर्णतः काले रंग की थीम का उपयोग करें + विश्राम + रंग स्कीम चुनें + थीम चुनें + रंग + रंग स्कीम + पूर्ण + काला + डायनामिक + बंद करें + प्रतिदिन ध्यान (औसत) + पिछले महीने + पिछले सप्ताह + ध्वनि + पिछले साल + सफ़ेद + दीर्घ विश्राम + %1$s मिनट शेष + मासिक उत्पादकता विश्लेषण + अधिक + अधिक जानकारी + ठीक + रोकें + रुका हुआ + शुरू करें + एक \"सत्र\" पोमोडोरो अंतरालों का एक क्रम होता है जिसमें ध्यान अंतराल, लघु विश्राम अंतराल और एक दीर्घ विश्राम अंतराल शामिल होता है। सत्र का अंतिम विश्राम हमेशा एक दीर्घ विश्राम होता है। + उत्पादकता विश्लेषण + दिन के अलग-अलग समय पर ध्यान अवधि + पुनः शुरू करें + सत्र की अवधि + एक सत्र में ध्यान अंतराल: %1$d + सेटिंग + लघु विश्राम + अगला अंतराल + अगले पर जाएं + अगला शुरू करें + आँकड़े + अलार्म बंद करें + वर्तमान टाइमर सत्र पूरा हो गया है। अलार्म बंद करने के लिए कहीं भी टैप करें। + अलार्म बंद करें? + सिस्टम + थीम + टाइमर + टाइमर पूर्णता + %2$d में से %1$d + आज + आगामी + आगामी: %1$s (%2$s) + वाइब्रेट + टाइमर पूरा होने पर वाइब्रेट करें + साप्ताहिक उत्पादकता विश्लेषण + दिखावट + अवधियां diff --git a/app/src/main/res/values-uk/strings.xml b/app/src/main/res/values-uk/strings.xml index f20c905..73a30fe 100644 --- a/app/src/main/res/values-uk/strings.xml +++ b/app/src/main/res/values-uk/strings.xml @@ -35,7 +35,7 @@ ОК Динамічна Колір - Налаштування системи + Система Сигнал Світла Темна @@ -57,4 +57,9 @@ Пауза Грати Минулого року + Always On Display + Натисніть будь-де під час перегляду таймера, щоб перейти в режим AOD + Вигляд + Тривалість + Звук diff --git a/app/src/main/res/values-zh-rCN/strings.xml b/app/src/main/res/values-zh-rCN/strings.xml index ad99d0d..8463744 100644 --- a/app/src/main/res/values-zh-rCN/strings.xml +++ b/app/src/main/res/values-zh-rCN/strings.xml @@ -18,7 +18,7 @@ 配色方案 动态 颜色 - 系统默认 + 系统 响铃 亮色 暗色 @@ -59,4 +59,7 @@ 去年 息屏显示 查看计时器时点击任意位置切换至 AOD 模式 + 外观 + 时长 + 声音 diff --git a/fastlane/metadata/android/hi-IN/full_description.txt b/fastlane/metadata/android/hi-IN/full_description.txt new file mode 100644 index 0000000..fe2fe9f --- /dev/null +++ b/fastlane/metadata/android/hi-IN/full_description.txt @@ -0,0 +1,12 @@ +टोमैटो एंड्रॉइड के लिए मटेरियल 3 एक्सप्रेसिव पर आधारित एक न्यूनतम पोमोडोरो टाइमर है। + +टोमैटो पूरी तरह से मुफ़्त और ओपन-सोर्स है, हमेशा के लिए। आप https://github.com/nsh07/Tomato पर सोर्स कोड पा सकते हैं, बग रिपोर्ट कर सकते हैं या सुविधाएँ सुझा सकते हैं। + +विशेषताएँ: +- नवीनतम मटेरियल 3 एक्सप्रेसिव दिशानिर्देशों पर आधारित सरल, न्यूनतम UI +- समझने में आसान तरीके से काम/अध्ययन समय के विस्तृत आँकड़े + - एक नज़र में वर्तमान दिन के आँकड़े देखें + - पढ़ने में आसान, साफ़ ग्राफ़ में दिखाए गए पिछले हफ़्ते और पिछले महीने के आँकड़े देखें + - पिछले हफ़्ते और महीने के अतिरिक्त आँकड़े जो दिखाते हैं कि दिन के किस समय आप सबसे ज़्यादा उत्पादक होते हैं +- अनुकूलन योग्य टाइमर पैरामीटर +- एंड्रॉइड 16 लाइव अपडेट From fdbc4e16d032850e90ba6bb5929e5529dc62ad6c Mon Sep 17 00:00:00 2001 From: Nishant Mishra Date: Sat, 25 Oct 2025 09:07:19 +0530 Subject: [PATCH 04/25] feat(system): add notification manager system service for DND --- app/src/main/AndroidManifest.xml | 1 + app/src/main/java/org/nsh07/pomodoro/data/AppContainer.kt | 5 +++++ app/src/main/java/org/nsh07/pomodoro/service/TimerService.kt | 4 ++-- 3 files changed, 8 insertions(+), 2 deletions(-) diff --git a/app/src/main/AndroidManifest.xml b/app/src/main/AndroidManifest.xml index 3f3f018..62a7ee8 100644 --- a/app/src/main/AndroidManifest.xml +++ b/app/src/main/AndroidManifest.xml @@ -18,6 +18,7 @@ + diff --git a/app/src/main/java/org/nsh07/pomodoro/data/AppContainer.kt b/app/src/main/java/org/nsh07/pomodoro/data/AppContainer.kt index f36a179..4ca23c9 100644 --- a/app/src/main/java/org/nsh07/pomodoro/data/AppContainer.kt +++ b/app/src/main/java/org/nsh07/pomodoro/data/AppContainer.kt @@ -17,6 +17,7 @@ package org.nsh07.pomodoro.data +import android.app.NotificationManager import android.app.PendingIntent import android.content.Context import androidx.compose.ui.graphics.Color @@ -34,6 +35,7 @@ interface AppContainer { val appStatRepository: AppStatRepository val appTimerRepository: AppTimerRepository val notificationManager: NotificationManagerCompat + val notificationManagerService: NotificationManager val notificationBuilder: NotificationCompat.Builder val timerState: MutableStateFlow val time: MutableStateFlow @@ -56,6 +58,9 @@ class DefaultAppContainer(context: Context) : AppContainer { NotificationManagerCompat.from(context) } + override val notificationManagerService: NotificationManager = + context.getSystemService(Context.NOTIFICATION_SERVICE) as NotificationManager + override val notificationBuilder: NotificationCompat.Builder by lazy { NotificationCompat.Builder(context, "timer") .setSmallIcon(R.drawable.tomato_logo_notification) diff --git a/app/src/main/java/org/nsh07/pomodoro/service/TimerService.kt b/app/src/main/java/org/nsh07/pomodoro/service/TimerService.kt index b2423d1..d1ff85f 100644 --- a/app/src/main/java/org/nsh07/pomodoro/service/TimerService.kt +++ b/app/src/main/java/org/nsh07/pomodoro/service/TimerService.kt @@ -30,7 +30,6 @@ import android.os.Vibrator import android.os.VibratorManager import androidx.compose.ui.graphics.toArgb import androidx.core.app.NotificationCompat -import androidx.core.app.NotificationManagerCompat import kotlinx.coroutines.CoroutineScope import kotlinx.coroutines.Dispatchers import kotlinx.coroutines.Job @@ -53,7 +52,8 @@ class TimerService : Service() { private val timerRepository by lazy { appContainer.appTimerRepository } private val statRepository by lazy { appContainer.appStatRepository } - private val notificationManager by lazy { NotificationManagerCompat.from(this) } + private val notificationManager by lazy { appContainer.notificationManager } + private val notificationManagerService by lazy { appContainer.notificationManagerService } private val notificationBuilder by lazy { appContainer.notificationBuilder } private val _timerState by lazy { appContainer.timerState } private val _time by lazy { appContainer.time } From 3deaab0a13b665952862a4df04d2f5fb1d283a73 Mon Sep 17 00:00:00 2001 From: "renovate[bot]" <29139614+renovate[bot]@users.noreply.github.com> Date: Fri, 24 Oct 2025 23:29:18 +0000 Subject: [PATCH 05/25] chore(deps): update actions/upload-artifact action to v5 --- .github/workflows/android.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/android.yml b/.github/workflows/android.yml index e21b4fc..20d993c 100644 --- a/.github/workflows/android.yml +++ b/.github/workflows/android.yml @@ -25,7 +25,7 @@ jobs: run: ./gradlew testDebugUnitTest - name: Upload debug APK artifact - uses: actions/upload-artifact@v4 + uses: actions/upload-artifact@v5 with: name: tomato-debug path: ./app/build/outputs/apk/debug/app-debug.apk From a18d56e4d054b8aca23b134664b6f64329bf706c Mon Sep 17 00:00:00 2001 From: Nishant Mishra Date: Sat, 25 Oct 2025 13:19:08 +0530 Subject: [PATCH 06/25] feat(system): update dnd status while running the timer --- .../org/nsh07/pomodoro/service/TimerService.kt | 17 ++++++++++++++++- .../pomodoro/ui/timerScreen/TimerScreen.kt | 15 +++++++++++++-- 2 files changed, 29 insertions(+), 3 deletions(-) diff --git a/app/src/main/java/org/nsh07/pomodoro/service/TimerService.kt b/app/src/main/java/org/nsh07/pomodoro/service/TimerService.kt index d1ff85f..0501044 100644 --- a/app/src/main/java/org/nsh07/pomodoro/service/TimerService.kt +++ b/app/src/main/java/org/nsh07/pomodoro/service/TimerService.kt @@ -18,6 +18,7 @@ package org.nsh07.pomodoro.service import android.annotation.SuppressLint +import android.app.NotificationManager import android.app.Service import android.content.Intent import android.media.AudioAttributes @@ -106,6 +107,7 @@ class TimerService : Service() { runBlocking { job.cancel() saveTimeToDb() + setDoNotDisturb(false) notificationManager.cancel(1) alarm?.release() } @@ -140,6 +142,7 @@ class TimerService : Service() { updateProgressSegments() if (timerState.value.timerRunning) { + setDoNotDisturb(false) notificationBuilder.clearActions().addTimerActions( this, R.drawable.play, getString(R.string.start) ) @@ -149,6 +152,8 @@ class TimerService : Service() { } pauseTime = SystemClock.elapsedRealtime() } else { + if (timerState.value.timerMode == TimerMode.FOCUS) setDoNotDisturb(true) + else setDoNotDisturb(false) notificationBuilder.clearActions().addTimerActions( this, R.drawable.pause, getString(R.string.stop) ) @@ -337,6 +342,7 @@ class TimerService : Service() { cycles = (cycles + 1) % (timerRepository.sessionLength * 2) if (cycles % 2 == 0) { + if (timerState.value.timerRunning) setDoNotDisturb(true) time = timerRepository.focusTime _timerState.update { currentState -> currentState.copy( @@ -354,6 +360,7 @@ class TimerService : Service() { ) } } else { + if (timerState.value.timerRunning) setDoNotDisturb(false) val long = cycles == (timerRepository.sessionLength * 2) - 1 time = if (long) timerRepository.longBreakTime else timerRepository.shortBreakTime @@ -441,7 +448,15 @@ class TimerService : Service() { } } - fun updateAlarmTone() { + private fun setDoNotDisturb(doNotDisturb: Boolean) { + if (notificationManagerService.isNotificationPolicyAccessGranted()) { + if (doNotDisturb) { + notificationManagerService.setInterruptionFilter(NotificationManager.INTERRUPTION_FILTER_ALARMS) + } else notificationManagerService.setInterruptionFilter(NotificationManager.INTERRUPTION_FILTER_ALL) + } + } + + private fun updateAlarmTone() { alarm?.release() alarm = initializeMediaPlayer() } 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 68b9094..ee77820 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 @@ -1,8 +1,18 @@ /* * Copyright (c) 2025 Nishant Mishra * - * You should have received a copy of the GNU General Public License - * along with this program. If not, see . + * 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.timerScreen @@ -92,6 +102,7 @@ import org.nsh07.pomodoro.ui.timerScreen.viewModel.TimerAction import org.nsh07.pomodoro.ui.timerScreen.viewModel.TimerMode import org.nsh07.pomodoro.ui.timerScreen.viewModel.TimerState + @OptIn(ExperimentalMaterial3Api::class, ExperimentalMaterial3ExpressiveApi::class) @Composable fun SharedTransitionScope.TimerScreen( From d3cead00abd5c67ba94b44b001684cf99a4ae3e5 Mon Sep 17 00:00:00 2001 From: Nishant Mishra Date: Sat, 25 Oct 2025 14:06:48 +0530 Subject: [PATCH 07/25] feat(ui): update bmc logo --- .../ui/settingsScreen/components/AboutCard.kt | 4 ++- app/src/main/res/drawable/bmc.xml | 30 +++++++++++++++++++ app/src/main/res/drawable/coffee.xml | 9 ------ 3 files changed, 33 insertions(+), 10 deletions(-) create mode 100644 app/src/main/res/drawable/bmc.xml delete mode 100644 app/src/main/res/drawable/coffee.xml 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 fe0e1ce..3bf2f6c 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 @@ -24,6 +24,7 @@ import androidx.compose.foundation.layout.FlowRow import androidx.compose.foundation.layout.Row import androidx.compose.foundation.layout.Spacer import androidx.compose.foundation.layout.fillMaxWidth +import androidx.compose.foundation.layout.height import androidx.compose.foundation.layout.padding import androidx.compose.foundation.layout.size import androidx.compose.material3.Button @@ -123,8 +124,9 @@ fun AboutCard(modifier: Modifier = Modifier) { verticalAlignment = Alignment.CenterVertically ) { Icon( - painterResource(R.drawable.coffee), + painterResource(R.drawable.bmc), contentDescription = "Buy me a coffee", + modifier = Modifier.height(24.dp) ) Text(text = "Buy me a coffee") diff --git a/app/src/main/res/drawable/bmc.xml b/app/src/main/res/drawable/bmc.xml new file mode 100644 index 0000000..110fa4b --- /dev/null +++ b/app/src/main/res/drawable/bmc.xml @@ -0,0 +1,30 @@ + + + + + + diff --git a/app/src/main/res/drawable/coffee.xml b/app/src/main/res/drawable/coffee.xml deleted file mode 100644 index 05b913c..0000000 --- a/app/src/main/res/drawable/coffee.xml +++ /dev/null @@ -1,9 +0,0 @@ - - - From fddc1f8ed3eb4d2b62c286897e6b284f6fb0d969 Mon Sep 17 00:00:00 2001 From: Nishant Mishra Date: Sat, 25 Oct 2025 14:27:25 +0530 Subject: [PATCH 08/25] feat(settings): implement a settings option to enable auto-dnd --- .../nsh07/pomodoro/data/TimerRepository.kt | 16 +++- .../nsh07/pomodoro/service/TimerService.kt | 82 +++++++++---------- .../ui/settingsScreen/SettingsScreen.kt | 7 ++ .../settingsScreen/screens/TimerSettings.kt | 68 ++++++++++++--- .../viewModel/SettingsViewModel.kt | 9 ++ .../timerScreen/viewModel/TimerViewModel.kt | 17 +++- app/src/main/res/drawable/dnd.xml | 26 ++++++ app/src/main/res/values/strings.xml | 2 + 8 files changed, 171 insertions(+), 56 deletions(-) create mode 100644 app/src/main/res/drawable/dnd.xml diff --git a/app/src/main/java/org/nsh07/pomodoro/data/TimerRepository.kt b/app/src/main/java/org/nsh07/pomodoro/data/TimerRepository.kt index a7a7b46..788d1af 100644 --- a/app/src/main/java/org/nsh07/pomodoro/data/TimerRepository.kt +++ b/app/src/main/java/org/nsh07/pomodoro/data/TimerRepository.kt @@ -1,8 +1,18 @@ /* * Copyright (c) 2025 Nishant Mishra * - * You should have received a copy of the GNU General Public License - * along with this program. If not, see . + * 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.data @@ -27,6 +37,7 @@ interface TimerRepository { var alarmEnabled: Boolean var vibrateEnabled: Boolean + var dndEnabled: Boolean var colorScheme: ColorScheme @@ -46,6 +57,7 @@ class AppTimerRepository : TimerRepository { override var timerFrequency: Float = 10f override var alarmEnabled = true override var vibrateEnabled = true + override var dndEnabled: Boolean = false override var colorScheme = lightColorScheme() override var alarmSoundUri: Uri? = Settings.System.DEFAULT_ALARM_ALERT_URI ?: Settings.System.DEFAULT_RINGTONE_URI diff --git a/app/src/main/java/org/nsh07/pomodoro/service/TimerService.kt b/app/src/main/java/org/nsh07/pomodoro/service/TimerService.kt index 0501044..8932c50 100644 --- a/app/src/main/java/org/nsh07/pomodoro/service/TimerService.kt +++ b/app/src/main/java/org/nsh07/pomodoro/service/TimerService.kt @@ -129,7 +129,7 @@ class TimerService : Service() { } } - Actions.SKIP.toString() -> skipTimer(true) + Actions.SKIP.toString() -> skipScope.launch { skipTimer(true) } Actions.STOP_ALARM.toString() -> stopAlarm() @@ -329,50 +329,48 @@ class TimerService : Service() { } } - private fun skipTimer(fromButton: Boolean = false) { + private suspend fun skipTimer(fromButton: Boolean = false) { updateProgressSegments() - skipScope.launch { - saveTimeToDb() - updateProgressSegments() - showTimerNotification(0, paused = true, complete = !fromButton) - startTime = 0L - pauseTime = 0L - pauseDuration = 0L + saveTimeToDb() + updateProgressSegments() + showTimerNotification(0, paused = true, complete = !fromButton) + startTime = 0L + pauseTime = 0L + pauseDuration = 0L - cycles = (cycles + 1) % (timerRepository.sessionLength * 2) + cycles = (cycles + 1) % (timerRepository.sessionLength * 2) - if (cycles % 2 == 0) { - if (timerState.value.timerRunning) setDoNotDisturb(true) - time = timerRepository.focusTime - _timerState.update { currentState -> - currentState.copy( - timerMode = TimerMode.FOCUS, - timeStr = millisecondsToStr(time), - totalTime = time, - nextTimerMode = if (cycles == (timerRepository.sessionLength - 1) * 2) TimerMode.LONG_BREAK else TimerMode.SHORT_BREAK, - nextTimeStr = if (cycles == (timerRepository.sessionLength - 1) * 2) millisecondsToStr( - timerRepository.longBreakTime - ) else millisecondsToStr( - timerRepository.shortBreakTime - ), - currentFocusCount = cycles / 2 + 1, - totalFocusCount = timerRepository.sessionLength - ) - } - } else { - if (timerState.value.timerRunning) setDoNotDisturb(false) - val long = cycles == (timerRepository.sessionLength * 2) - 1 - time = if (long) timerRepository.longBreakTime else timerRepository.shortBreakTime + if (cycles % 2 == 0) { + if (timerState.value.timerRunning) setDoNotDisturb(true) + time = timerRepository.focusTime + _timerState.update { currentState -> + currentState.copy( + timerMode = TimerMode.FOCUS, + timeStr = millisecondsToStr(time), + totalTime = time, + nextTimerMode = if (cycles == (timerRepository.sessionLength - 1) * 2) TimerMode.LONG_BREAK else TimerMode.SHORT_BREAK, + nextTimeStr = if (cycles == (timerRepository.sessionLength - 1) * 2) millisecondsToStr( + timerRepository.longBreakTime + ) else millisecondsToStr( + timerRepository.shortBreakTime + ), + currentFocusCount = cycles / 2 + 1, + totalFocusCount = timerRepository.sessionLength + ) + } + } else { + if (timerState.value.timerRunning) setDoNotDisturb(false) + val long = cycles == (timerRepository.sessionLength * 2) - 1 + time = if (long) timerRepository.longBreakTime else timerRepository.shortBreakTime - _timerState.update { currentState -> - currentState.copy( - timerMode = if (long) TimerMode.LONG_BREAK else TimerMode.SHORT_BREAK, - timeStr = millisecondsToStr(time), - totalTime = time, - nextTimerMode = TimerMode.FOCUS, - nextTimeStr = millisecondsToStr(timerRepository.focusTime) - ) - } + _timerState.update { currentState -> + currentState.copy( + timerMode = if (long) TimerMode.LONG_BREAK else TimerMode.SHORT_BREAK, + timeStr = millisecondsToStr(time), + totalTime = time, + nextTimerMode = TimerMode.FOCUS, + nextTimeStr = millisecondsToStr(timerRepository.focusTime) + ) } } } @@ -449,7 +447,7 @@ class TimerService : Service() { } private fun setDoNotDisturb(doNotDisturb: Boolean) { - if (notificationManagerService.isNotificationPolicyAccessGranted()) { + if (timerRepository.dndEnabled && notificationManagerService.isNotificationPolicyAccessGranted()) { if (doNotDisturb) { notificationManagerService.setInterruptionFilter(NotificationManager.INTERRUPTION_FILTER_ALARMS) } else notificationManagerService.setInterruptionFilter(NotificationManager.INTERRUPTION_FILTER_ALL) 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 512df9a..a22b1f5 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 @@ -104,6 +104,7 @@ fun SettingsScreenRoot( val alarmEnabled by viewModel.alarmEnabled.collectAsStateWithLifecycle(true) val vibrateEnabled by viewModel.vibrateEnabled.collectAsStateWithLifecycle(true) + val dndEnabled by viewModel.dndEnabled.collectAsStateWithLifecycle(false) val alarmSound by viewModel.alarmSound.collectAsStateWithLifecycle(viewModel.currentAlarmSound) val preferencesState by viewModel.preferencesState.collectAsStateWithLifecycle() @@ -126,11 +127,13 @@ fun SettingsScreenRoot( sessionsSliderState = sessionsSliderState, alarmEnabled = alarmEnabled, vibrateEnabled = vibrateEnabled, + dndEnabled = dndEnabled, alarmSound = alarmSound, onAlarmEnabledChange = viewModel::saveAlarmEnabled, onVibrateEnabledChange = viewModel::saveVibrateEnabled, onBlackThemeChange = viewModel::saveBlackTheme, onAodEnabledChange = viewModel::saveAodEnabled, + onDndEnabledChange = viewModel::saveDndEnabled, onAlarmSoundChanged = { viewModel.saveAlarmSound(it) Intent(context, TimerService::class.java).apply { @@ -155,11 +158,13 @@ private fun SettingsScreen( sessionsSliderState: SliderState, alarmEnabled: Boolean, vibrateEnabled: Boolean, + dndEnabled: Boolean, alarmSound: String, onAlarmEnabledChange: (Boolean) -> Unit, onVibrateEnabledChange: (Boolean) -> Unit, onBlackThemeChange: (Boolean) -> Unit, onAodEnabledChange: (Boolean) -> Unit, + onDndEnabledChange: (Boolean) -> Unit, onAlarmSoundChanged: (Uri?) -> Unit, onThemeChange: (String) -> Unit, onColorSchemeChange: (Color) -> Unit, @@ -270,11 +275,13 @@ private fun SettingsScreen( entry { TimerSettings( aodEnabled = preferencesState.aodEnabled, + dndEnabled = dndEnabled, focusTimeInputFieldState = focusTimeInputFieldState, shortBreakTimeInputFieldState = shortBreakTimeInputFieldState, longBreakTimeInputFieldState = longBreakTimeInputFieldState, sessionsSliderState = sessionsSliderState, onAodEnabledChange = onAodEnabledChange, + onDndEnabledChange = onDndEnabledChange, onBack = backStack::removeLastOrNull ) } diff --git a/app/src/main/java/org/nsh07/pomodoro/ui/settingsScreen/screens/TimerSettings.kt b/app/src/main/java/org/nsh07/pomodoro/ui/settingsScreen/screens/TimerSettings.kt index 01dddba..421140c 100644 --- a/app/src/main/java/org/nsh07/pomodoro/ui/settingsScreen/screens/TimerSettings.kt +++ b/app/src/main/java/org/nsh07/pomodoro/ui/settingsScreen/screens/TimerSettings.kt @@ -17,6 +17,11 @@ package org.nsh07.pomodoro.ui.settingsScreen.screens +import android.app.NotificationManager +import android.content.Context +import android.content.Intent +import android.provider.Settings +import android.widget.Toast import androidx.compose.animation.AnimatedVisibility import androidx.compose.foundation.background import androidx.compose.foundation.horizontalScroll @@ -31,6 +36,7 @@ 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.rememberScrollState import androidx.compose.foundation.shape.RoundedCornerShape import androidx.compose.foundation.text.input.TextFieldState @@ -51,6 +57,7 @@ import androidx.compose.material3.SwitchDefaults import androidx.compose.material3.Text import androidx.compose.material3.TopAppBarDefaults import androidx.compose.runtime.Composable +import androidx.compose.runtime.LaunchedEffect import androidx.compose.runtime.getValue import androidx.compose.runtime.mutableStateOf import androidx.compose.runtime.remember @@ -59,6 +66,7 @@ import androidx.compose.ui.Alignment import androidx.compose.ui.Modifier import androidx.compose.ui.draw.clip import androidx.compose.ui.input.nestedscroll.nestedScroll +import androidx.compose.ui.platform.LocalContext import androidx.compose.ui.res.painterResource import androidx.compose.ui.res.stringResource import androidx.compose.ui.text.input.ImeAction @@ -76,19 +84,58 @@ import org.nsh07.pomodoro.ui.theme.TomatoShapeDefaults.cardShape import org.nsh07.pomodoro.ui.theme.TomatoShapeDefaults.middleListItemShape import org.nsh07.pomodoro.ui.theme.TomatoShapeDefaults.topListItemShape + @OptIn(ExperimentalMaterial3Api::class, ExperimentalMaterial3ExpressiveApi::class) @Composable fun TimerSettings( aodEnabled: Boolean, + dndEnabled: Boolean, focusTimeInputFieldState: TextFieldState, shortBreakTimeInputFieldState: TextFieldState, longBreakTimeInputFieldState: TextFieldState, sessionsSliderState: SliderState, onAodEnabledChange: (Boolean) -> Unit, + onDndEnabledChange: (Boolean) -> Unit, onBack: () -> Unit, modifier: Modifier = Modifier ) { val scrollBehavior = TopAppBarDefaults.enterAlwaysScrollBehavior() + val context = LocalContext.current + val appName = stringResource(R.string.app_name) + val notificationManagerService = + remember { context.getSystemService(Context.NOTIFICATION_SERVICE) as NotificationManager } + + LaunchedEffect(Unit) { + if (!notificationManagerService.isNotificationPolicyAccessGranted()) + onDndEnabledChange(false) + } + + val switchItems = listOf( + SettingsSwitchItem( + checked = dndEnabled, + icon = R.drawable.dnd, + label = R.string.dnd, + description = R.string.dnd_desc, + onClick = { + if (it && !notificationManagerService.isNotificationPolicyAccessGranted()) { + val intent = Intent(Settings.ACTION_NOTIFICATION_POLICY_ACCESS_SETTINGS) + Toast.makeText(context, "Enable permission for \"$appName\"", Toast.LENGTH_LONG) + .show() + context.startActivity(intent) + } else if (!it && notificationManagerService.isNotificationPolicyAccessGranted()) { + notificationManagerService.setInterruptionFilter(NotificationManager.INTERRUPTION_FILTER_ALL) + } + onDndEnabledChange(it) + } + ), + SettingsSwitchItem( + checked = aodEnabled, + icon = R.drawable.aod, + label = R.string.always_on_display, + description = R.string.always_on_display_desc, + onClick = onAodEnabledChange + ) + ) Column(modifier.nestedScroll(scrollBehavior.nestedScrollConnection)) { LargeFlexibleTopAppBar( @@ -213,14 +260,7 @@ fun TimerSettings( ) } item { Spacer(Modifier.height(12.dp)) } - item { - val item = SettingsSwitchItem( - checked = aodEnabled, - icon = R.drawable.aod, - label = R.string.always_on_display, - description = R.string.always_on_display_desc, - onClick = onAodEnabledChange - ) + itemsIndexed(switchItems) { index, item -> ListItem( leadingContent = { Icon( @@ -254,7 +294,13 @@ fun TimerSettings( ) }, colors = listItemColors, - modifier = Modifier.clip(cardShape) + modifier = Modifier.clip( + when (index) { + 0 -> topListItemShape + switchItems.size - 1 -> bottomListItemShape + else -> middleListItemShape + } + ) ) } @@ -311,7 +357,9 @@ private fun TimerSettingsPreview() { longBreakTimeInputFieldState = longBreakTimeInputFieldState, sessionsSliderState = sessionsSliderState, aodEnabled = true, + dndEnabled = false, onBack = {}, - onAodEnabledChange = {} + onAodEnabledChange = {}, + onDndEnabledChange = {} ) } \ No newline at end of file diff --git a/app/src/main/java/org/nsh07/pomodoro/ui/settingsScreen/viewModel/SettingsViewModel.kt b/app/src/main/java/org/nsh07/pomodoro/ui/settingsScreen/viewModel/SettingsViewModel.kt index 76ebb8c..0a3262f 100644 --- a/app/src/main/java/org/nsh07/pomodoro/ui/settingsScreen/viewModel/SettingsViewModel.kt +++ b/app/src/main/java/org/nsh07/pomodoro/ui/settingsScreen/viewModel/SettingsViewModel.kt @@ -85,6 +85,8 @@ class SettingsViewModel( preferenceRepository.getBooleanPreferenceFlow("alarm_enabled").distinctUntilChanged() val vibrateEnabled = preferenceRepository.getBooleanPreferenceFlow("vibrate_enabled").distinctUntilChanged() + val dndEnabled = + preferenceRepository.getBooleanPreferenceFlow("dnd_enabled").distinctUntilChanged() init { viewModelScope.launch { @@ -179,6 +181,13 @@ class SettingsViewModel( } } + fun saveDndEnabled(enabled: Boolean) { + viewModelScope.launch { + timerRepository.dndEnabled = enabled + preferenceRepository.saveBooleanPreference("dnd_enabled", enabled) + } + } + fun saveAlarmSound(uri: Uri?) { viewModelScope.launch { timerRepository.alarmSoundUri = uri diff --git a/app/src/main/java/org/nsh07/pomodoro/ui/timerScreen/viewModel/TimerViewModel.kt b/app/src/main/java/org/nsh07/pomodoro/ui/timerScreen/viewModel/TimerViewModel.kt index 53c23b5..2c4e493 100644 --- a/app/src/main/java/org/nsh07/pomodoro/ui/timerScreen/viewModel/TimerViewModel.kt +++ b/app/src/main/java/org/nsh07/pomodoro/ui/timerScreen/viewModel/TimerViewModel.kt @@ -1,8 +1,18 @@ /* * Copyright (c) 2025 Nishant Mishra * - * You should have received a copy of the GNU General Public License - * along with this program. If not, see . + * 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.timerScreen.viewModel @@ -85,6 +95,9 @@ class TimerViewModel( timerRepository.vibrateEnabled = preferenceRepository.getBooleanPreference("vibrate_enabled") ?: preferenceRepository.saveBooleanPreference("vibrate_enabled", true) + timerRepository.dndEnabled = + preferenceRepository.getBooleanPreference("dnd_enabled") + ?: preferenceRepository.saveBooleanPreference("dnd_enabled", false) timerRepository.alarmSoundUri = ( preferenceRepository.getStringPreference("alarm_sound") diff --git a/app/src/main/res/drawable/dnd.xml b/app/src/main/res/drawable/dnd.xml new file mode 100644 index 0000000..16113b4 --- /dev/null +++ b/app/src/main/res/drawable/dnd.xml @@ -0,0 +1,26 @@ + + + + + diff --git a/app/src/main/res/values/strings.xml b/app/src/main/res/values/strings.xml index cf51e15..f4c25b8 100644 --- a/app/src/main/res/values/strings.xml +++ b/app/src/main/res/values/strings.xml @@ -79,4 +79,6 @@ Appearance Durations Sound + Do Not Disturb + Turn on DND when running a Focus timer \ No newline at end of file From 9c6282e10534d2b19229f2c4b1363c6b893b1c5b Mon Sep 17 00:00:00 2001 From: Nishant Mishra Date: Sun, 26 Oct 2025 08:16:41 +0530 Subject: [PATCH 09/25] feat(build): add play build flavor for paywall --- app/build.gradle.kts | 15 +++++++++++++++ app/src/play/AndroidManifest.xml | 21 +++++++++++++++++++++ gradle/libs.versions.toml | 2 ++ 3 files changed, 38 insertions(+) create mode 100644 app/src/play/AndroidManifest.xml diff --git a/app/build.gradle.kts b/app/build.gradle.kts index 139e2d9..be26edf 100644 --- a/app/build.gradle.kts +++ b/app/build.gradle.kts @@ -58,6 +58,19 @@ android { ) } } + + flavorDimensions += "version" + productFlavors { + create("foss") { + dimension = "version" + isDefault = true + } + create("play") { + dimension = "version" + versionNameSuffix = "-play" + } + } + compileOptions { sourceCompatibility = JavaVersion.VERSION_17 targetCompatibility = JavaVersion.VERSION_17 @@ -103,6 +116,8 @@ dependencies { implementation(libs.androidx.room.ktx) ksp(libs.androidx.room.compiler) + "playImplementation"(libs.purchases) + testImplementation(libs.junit) androidTestImplementation(libs.androidx.junit) diff --git a/app/src/play/AndroidManifest.xml b/app/src/play/AndroidManifest.xml new file mode 100644 index 0000000..97908e4 --- /dev/null +++ b/app/src/play/AndroidManifest.xml @@ -0,0 +1,21 @@ + + + + + + \ No newline at end of file diff --git a/gradle/libs.versions.toml b/gradle/libs.versions.toml index 783dd5d..9356ceb 100644 --- a/gradle/libs.versions.toml +++ b/gradle/libs.versions.toml @@ -12,6 +12,7 @@ ksp = "2.2.20-2.0.4" lifecycleRuntimeKtx = "2.9.4" materialKolor = "3.0.1" navigation3 = "1.0.0-beta01" +purchases = "9.12.0" room = "2.8.3" vico = "2.2.1" @@ -39,6 +40,7 @@ androidx-ui-tooling = { group = "androidx.compose.ui", name = "ui-tooling" } androidx-ui-tooling-preview = { group = "androidx.compose.ui", name = "ui-tooling-preview" } junit = { group = "junit", name = "junit", version.ref = "junit" } material-kolor = { module = "com.materialkolor:material-kolor", version.ref = "materialKolor" } +purchases = { module = "com.revenuecat.purchases:purchases", version.ref = "purchases" } vico-compose-m3 = { group = "com.patrykandpatrick.vico", name = "compose-m3", version.ref = "vico" } [plugins] From fcab066fabd378cf80bfe448b416e71bc9bd3239 Mon Sep 17 00:00:00 2001 From: Nishant Mishra Date: Sun, 26 Oct 2025 08:23:40 +0530 Subject: [PATCH 10/25] ci: update build flavor name in CI to fix failing build --- .github/workflows/android.yml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/.github/workflows/android.yml b/.github/workflows/android.yml index 20d993c..7661929 100644 --- a/.github/workflows/android.yml +++ b/.github/workflows/android.yml @@ -19,10 +19,10 @@ jobs: run: chmod +x gradlew - name: Build debug APK with Gradle - run: ./gradlew assembleDebug + run: ./gradlew assembleFossDebug - name: Run tests - run: ./gradlew testDebugUnitTest + run: ./gradlew testFossDebugUnitTest - name: Upload debug APK artifact uses: actions/upload-artifact@v5 From 7aed88d1c50ebbb97b4eabf9c82d698d7aea8948 Mon Sep 17 00:00:00 2001 From: Nishant Mishra Date: Sun, 26 Oct 2025 08:25:27 +0530 Subject: [PATCH 11/25] chore(release): bump version --- app/build.gradle.kts | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/app/build.gradle.kts b/app/build.gradle.kts index be26edf..31e1df6 100644 --- a/app/build.gradle.kts +++ b/app/build.gradle.kts @@ -43,8 +43,8 @@ android { applicationId = "org.nsh07.pomodoro" minSdk = 27 targetSdk = 36 - versionCode = 15 - versionName = "1.6.0" + versionCode = 16 + versionName = "1.6.1" testInstrumentationRunner = "androidx.test.runner.AndroidJUnitRunner" } From 199c88c913b674be5815c4e4a6bfa9aa929395fd Mon Sep 17 00:00:00 2001 From: Hosted Weblate Date: Sun, 26 Oct 2025 12:02:50 +0100 Subject: [PATCH 12/25] Translated using Weblate (Chinese (Traditional Han script)) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Currently translated at 100.0% (65 of 65 strings) Translated using Weblate (Chinese (Traditional Han script)) Currently translated at 100.0% (15 of 15 strings) Translated using Weblate (Chinese (Simplified Han script)) Currently translated at 100.0% (65 of 65 strings) Translated using Weblate (Chinese (Simplified Han script)) Currently translated at 100.0% (15 of 15 strings) Translated using Weblate (German) Currently translated at 100.0% (63 of 63 strings) Translated using Weblate (German) Currently translated at 100.0% (15 of 15 strings) Co-authored-by: Elias Frey Co-authored-by: Hosted Weblate Co-authored-by: ezn24 Co-authored-by: 大王叫我来巡山 Translate-URL: https://hosted.weblate.org/projects/tomato/store-descriptions/de/ Translate-URL: https://hosted.weblate.org/projects/tomato/store-descriptions/zh_Hans/ Translate-URL: https://hosted.weblate.org/projects/tomato/store-descriptions/zh_Hant/ Translate-URL: https://hosted.weblate.org/projects/tomato/strings/de/ Translate-URL: https://hosted.weblate.org/projects/tomato/strings/zh_Hans/ Translate-URL: https://hosted.weblate.org/projects/tomato/strings/zh_Hant/ Translation: Tomato/Store descriptions Translation: Tomato/Strings --- app/src/main/res/values-de/strings.xml | 8 +++++++- app/src/main/res/values-zh-rCN/strings.xml | 2 ++ app/src/main/res/values-zh-rTW/strings.xml | 9 ++++++++- .../metadata/android/de-DE/full_description.txt | 13 ++++++++++++- .../metadata/android/zh-CN/full_description.txt | 8 ++++---- .../metadata/android/zh-TW/full_description.txt | 12 ++++++++++++ .../metadata/android/zh-TW/short_description.txt | 1 + 7 files changed, 46 insertions(+), 7 deletions(-) create mode 100644 fastlane/metadata/android/zh-TW/full_description.txt create mode 100644 fastlane/metadata/android/zh-TW/short_description.txt diff --git a/app/src/main/res/values-de/strings.xml b/app/src/main/res/values-de/strings.xml index 3c08f8f..789de99 100644 --- a/app/src/main/res/values-de/strings.xml +++ b/app/src/main/res/values-de/strings.xml @@ -18,7 +18,7 @@ Farbschema Dynamisch Farbe - Systemstandard + System Alarm Hell Dunkel @@ -56,4 +56,10 @@ Als nächstes Timer Timer-Fortschritt + Always-On Display + Tippe irgendwo, während der Timer angezeigt wird, um in den AOD-Modus zu wechseln. + Letztes Jahr + Aussehen + Dauer + Sound diff --git a/app/src/main/res/values-zh-rCN/strings.xml b/app/src/main/res/values-zh-rCN/strings.xml index 8463744..8ea12ee 100644 --- a/app/src/main/res/values-zh-rCN/strings.xml +++ b/app/src/main/res/values-zh-rCN/strings.xml @@ -62,4 +62,6 @@ 外观 时长 声音 + 勿扰 + 运行“专注”计时器时打开勿扰 diff --git a/app/src/main/res/values-zh-rTW/strings.xml b/app/src/main/res/values-zh-rTW/strings.xml index 6260170..832677b 100644 --- a/app/src/main/res/values-zh-rTW/strings.xml +++ b/app/src/main/res/values-zh-rTW/strings.xml @@ -18,7 +18,7 @@ 配色方案 動態 顏色 - 系統默認 + 系統 鬧鐘 亮色 暗色 @@ -57,4 +57,11 @@ 计时 计时进度 上年 + 熄屏模式 + 外觀 + 在查看計時器時,點擊任意位置即可切換至熄屏模式 + 持續時間 + 聲音 + 請勿打擾 + 在執行專注計時器時開啟勿擾模式 diff --git a/fastlane/metadata/android/de-DE/full_description.txt b/fastlane/metadata/android/de-DE/full_description.txt index 1c1fcad..a6e9c5e 100644 --- a/fastlane/metadata/android/de-DE/full_description.txt +++ b/fastlane/metadata/android/de-DE/full_description.txt @@ -1 +1,12 @@ -

Tomato ist ein minimalistischer Pomodoro-Timer für Android, der auf Material 3 Expressive basiert.


Funktionen:

+Tomato ist ein minimalistischer Pomodoro-Timer für Android, der auf Material 3 Expressive basiert. + +Tomato ist vollständig kostenlos und Open Source, für immer. Unter https://github.com/nsh07/Tomato finden Sie den Quellcode und können Fehler melden oder Funktionen vorschlagen + +Funktionen: +-Einfache, minimalistische Benutzeroberfläche, die auf den neuesten Material 3 Expressive-Richtlinien basiert +-Detaillierte Statistiken zu Arbeits-/Lernzeiten in leicht verständlicher Form + -Statistiken für den aktuellen Tag auf einen Blick sichtbar + -Statistiken für die letzte Woche und den letzten Monat in einer übersichtlichen und sauberen Grafik dargestellt + -Zusätzliche Statistiken für die letzte Woche und den letzten Monat zeigen, zu welcher Tageszeit Sie am produktivsten sind +-Anpassbare Timer Voreinstellungen +-Unterstützung für Android 16 Live-Updates diff --git a/fastlane/metadata/android/zh-CN/full_description.txt b/fastlane/metadata/android/zh-CN/full_description.txt index a1505f3..580c24f 100644 --- a/fastlane/metadata/android/zh-CN/full_description.txt +++ b/fastlane/metadata/android/zh-CN/full_description.txt @@ -1,12 +1,12 @@ -Tomato 是一个基于Material 3 Expressive的安卓极简主义番茄钟. +Tomato 是一个基于Material 3 Expressive 的安卓极简主义番茄钟。 -Tomato 将永远保持完全免费和开源。如果你想获取源代码、报告程序错误(bug)或建议新功能,请访问 https://github.com/nsh07/Tomato。 +Tomato 将永远保持完全免费和开源。如果你想获取源代码、报告程序错误(bug)或建议新功能,请访问 https://github.com/nsh07/Tomato 功能: - 基于最新Material 3 Expressive指南的简洁用户界面 -- 以便于理解的方式提供工作/学习的详细统计数据 +- 以便于理解的方式提供工作/学习时间的详细统计数据 - 当日统计数据一目了然 - 清楚易读的上周和上月统计图表 - 上周和上月的额外统计数据帮您找到一天中最高效的时间段 - 可自定义的计时器参数 -- 支持 Android 16 即時更新 (Android 16 Live Updates) +- 支持 Android 16 即时更新 (Android 16 Live Updates) diff --git a/fastlane/metadata/android/zh-TW/full_description.txt b/fastlane/metadata/android/zh-TW/full_description.txt new file mode 100644 index 0000000..558c1fe --- /dev/null +++ b/fastlane/metadata/android/zh-TW/full_description.txt @@ -0,0 +1,12 @@ +Tomato 是一款基於 Material 3 Expressive 的 Android 極簡番茄鐘計時器。 + +Tomato 完全免費且開源,永遠如此。你可以在 https://github.com/nsh07/Tomato 取得原始碼,並回報問題或提出功能建議。 + +功能: +- 依循最新 Material 3 Expressive 設計規範的簡潔、極簡介面 +- 以易懂方式呈現工作/讀書時間的詳細統計 + - 當日統計一目了然 + - 過去一週與一個月的統計,以清爽易讀的圖表呈現 + - 另外提供過去一週與一個月在一天中何時最有效率的統計 +- 計時器參數可自訂 +- 支援 Android 16 的 Live Updates diff --git a/fastlane/metadata/android/zh-TW/short_description.txt b/fastlane/metadata/android/zh-TW/short_description.txt new file mode 100644 index 0000000..a817390 --- /dev/null +++ b/fastlane/metadata/android/zh-TW/short_description.txt @@ -0,0 +1 @@ +極簡番茄鐘 From 16b4a9f125309ff3a9a80c671031b80a23b42736 Mon Sep 17 00:00:00 2001 From: Nishant Mishra Date: Mon, 27 Oct 2025 11:31:07 +0530 Subject: [PATCH 13/25] feat(billing): implement a simple RevenueCat billing system Only for the Google Play version. The FOSS version remains free. --- app/build.gradle.kts | 3 +- .../pomodoro/billing/FossBillingManager.kt | 32 ++++++++++ .../billing/TomatoPlusPaywallDialog.kt | 27 ++++++++ .../pomodoro/billing/initializePurchases.kt | 22 +++++++ .../java/org/nsh07/pomodoro/MainActivity.kt | 6 +- .../org/nsh07/pomodoro/TomatoApplication.kt | 20 ++++++ .../nsh07/pomodoro/billing/BillingManager.kt | 24 +++++++ .../org/nsh07/pomodoro/data/AppContainer.kt | 5 ++ .../java/org/nsh07/pomodoro/ui/AppScreen.kt | 13 +++- .../ui/settingsScreen/SettingsScreen.kt | 49 +++++++++++++++ .../viewModel/SettingsViewModel.kt | 6 ++ .../pomodoro/billing/PlayBillingManager.kt | 58 +++++++++++++++++ .../billing/TomatoPlusPaywallDialog.kt | 63 +++++++++++++++++++ .../pomodoro/billing/initializePurchases.kt | 30 +++++++++ gradle/libs.versions.toml | 5 +- 15 files changed, 354 insertions(+), 9 deletions(-) create mode 100644 app/src/foss/java/org/nsh07/pomodoro/billing/FossBillingManager.kt create mode 100644 app/src/foss/java/org/nsh07/pomodoro/billing/TomatoPlusPaywallDialog.kt create mode 100644 app/src/foss/java/org/nsh07/pomodoro/billing/initializePurchases.kt create mode 100644 app/src/main/java/org/nsh07/pomodoro/billing/BillingManager.kt create mode 100644 app/src/play/java/org/nsh07/pomodoro/billing/PlayBillingManager.kt create mode 100644 app/src/play/java/org/nsh07/pomodoro/billing/TomatoPlusPaywallDialog.kt create mode 100644 app/src/play/java/org/nsh07/pomodoro/billing/initializePurchases.kt diff --git a/app/build.gradle.kts b/app/build.gradle.kts index 31e1df6..a396eba 100644 --- a/app/build.gradle.kts +++ b/app/build.gradle.kts @@ -116,7 +116,8 @@ dependencies { implementation(libs.androidx.room.ktx) ksp(libs.androidx.room.compiler) - "playImplementation"(libs.purchases) + "playImplementation"(libs.revenuecat.purchases) + "playImplementation"(libs.revenuecat.purchases.ui) testImplementation(libs.junit) diff --git a/app/src/foss/java/org/nsh07/pomodoro/billing/FossBillingManager.kt b/app/src/foss/java/org/nsh07/pomodoro/billing/FossBillingManager.kt new file mode 100644 index 0000000..4a155a3 --- /dev/null +++ b/app/src/foss/java/org/nsh07/pomodoro/billing/FossBillingManager.kt @@ -0,0 +1,32 @@ +/* + * 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.billing + +import kotlinx.coroutines.flow.MutableStateFlow +import kotlinx.coroutines.flow.asStateFlow + +/** + * Google Play implementation of BillingManager + */ +class FossBillingManager : BillingManager { + override val isPlus = MutableStateFlow(true).asStateFlow() +} + +object BillingManagerProvider { + val manager: BillingManager = FossBillingManager() +} \ No newline at end of file diff --git a/app/src/foss/java/org/nsh07/pomodoro/billing/TomatoPlusPaywallDialog.kt b/app/src/foss/java/org/nsh07/pomodoro/billing/TomatoPlusPaywallDialog.kt new file mode 100644 index 0000000..973041c --- /dev/null +++ b/app/src/foss/java/org/nsh07/pomodoro/billing/TomatoPlusPaywallDialog.kt @@ -0,0 +1,27 @@ +/* + * 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.billing + +import androidx.compose.runtime.Composable + +@Composable +fun TomatoPlusPaywallDialog( + isPlus: Boolean, + onDismiss: () -> Unit +) { +} \ No newline at end of file diff --git a/app/src/foss/java/org/nsh07/pomodoro/billing/initializePurchases.kt b/app/src/foss/java/org/nsh07/pomodoro/billing/initializePurchases.kt new file mode 100644 index 0000000..7a44002 --- /dev/null +++ b/app/src/foss/java/org/nsh07/pomodoro/billing/initializePurchases.kt @@ -0,0 +1,22 @@ +/* + * 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.billing + +import android.content.Context + +fun initializePurchases(context: Context) {} \ No newline at end of file diff --git a/app/src/main/java/org/nsh07/pomodoro/MainActivity.kt b/app/src/main/java/org/nsh07/pomodoro/MainActivity.kt index a129af6..4f34773 100644 --- a/app/src/main/java/org/nsh07/pomodoro/MainActivity.kt +++ b/app/src/main/java/org/nsh07/pomodoro/MainActivity.kt @@ -30,12 +30,10 @@ import androidx.lifecycle.compose.collectAsStateWithLifecycle import org.nsh07.pomodoro.ui.AppScreen import org.nsh07.pomodoro.ui.settingsScreen.viewModel.SettingsViewModel import org.nsh07.pomodoro.ui.theme.TomatoTheme -import org.nsh07.pomodoro.ui.timerScreen.viewModel.TimerViewModel import org.nsh07.pomodoro.utils.toColor class MainActivity : ComponentActivity() { - private val timerViewModel: TimerViewModel by viewModels(factoryProducer = { TimerViewModel.Factory }) private val settingsViewModel: SettingsViewModel by viewModels(factoryProducer = { SettingsViewModel.Factory }) private val appContainer by lazy { @@ -62,6 +60,8 @@ class MainActivity : ComponentActivity() { val seed = preferencesState.colorScheme.toColor() + val isPlus by settingsViewModel.isPlus.collectAsStateWithLifecycle() + TomatoTheme( darkTheme = darkTheme, seedColor = seed, @@ -73,7 +73,7 @@ class MainActivity : ComponentActivity() { } AppScreen( - timerViewModel = timerViewModel, + isPlus = isPlus, isAODEnabled = preferencesState.aodEnabled, setTimerFrequency = { appContainer.appTimerRepository.timerFrequency = it diff --git a/app/src/main/java/org/nsh07/pomodoro/TomatoApplication.kt b/app/src/main/java/org/nsh07/pomodoro/TomatoApplication.kt index 87be588..47de7fe 100644 --- a/app/src/main/java/org/nsh07/pomodoro/TomatoApplication.kt +++ b/app/src/main/java/org/nsh07/pomodoro/TomatoApplication.kt @@ -1,8 +1,26 @@ +/* + * 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 import android.app.Application import android.app.NotificationChannel import android.app.NotificationManager +import org.nsh07.pomodoro.billing.initializePurchases import org.nsh07.pomodoro.data.AppContainer import org.nsh07.pomodoro.data.DefaultAppContainer @@ -12,6 +30,8 @@ class TomatoApplication : Application() { super.onCreate() container = DefaultAppContainer(this) + initializePurchases(this) + val notificationChannel = NotificationChannel( "timer", getString(R.string.timer_progress), diff --git a/app/src/main/java/org/nsh07/pomodoro/billing/BillingManager.kt b/app/src/main/java/org/nsh07/pomodoro/billing/BillingManager.kt new file mode 100644 index 0000000..66b1659 --- /dev/null +++ b/app/src/main/java/org/nsh07/pomodoro/billing/BillingManager.kt @@ -0,0 +1,24 @@ +/* + * 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.billing + +import kotlinx.coroutines.flow.StateFlow + +interface BillingManager { + val isPlus: StateFlow +} \ No newline at end of file diff --git a/app/src/main/java/org/nsh07/pomodoro/data/AppContainer.kt b/app/src/main/java/org/nsh07/pomodoro/data/AppContainer.kt index 4ca23c9..bf445c8 100644 --- a/app/src/main/java/org/nsh07/pomodoro/data/AppContainer.kt +++ b/app/src/main/java/org/nsh07/pomodoro/data/AppContainer.kt @@ -26,6 +26,8 @@ import androidx.core.app.NotificationCompat import androidx.core.app.NotificationManagerCompat import kotlinx.coroutines.flow.MutableStateFlow import org.nsh07.pomodoro.R +import org.nsh07.pomodoro.billing.BillingManager +import org.nsh07.pomodoro.billing.BillingManagerProvider import org.nsh07.pomodoro.service.addTimerActions import org.nsh07.pomodoro.ui.timerScreen.viewModel.TimerState import org.nsh07.pomodoro.utils.millisecondsToStr @@ -34,6 +36,7 @@ interface AppContainer { val appPreferenceRepository: AppPreferenceRepository val appStatRepository: AppStatRepository val appTimerRepository: AppTimerRepository + val billingManager: BillingManager val notificationManager: NotificationManagerCompat val notificationManagerService: NotificationManager val notificationBuilder: NotificationCompat.Builder @@ -54,6 +57,8 @@ class DefaultAppContainer(context: Context) : AppContainer { override val appTimerRepository: AppTimerRepository by lazy { AppTimerRepository() } + override val billingManager: BillingManager by lazy { BillingManagerProvider.manager } + override val notificationManager: NotificationManagerCompat by lazy { NotificationManagerCompat.from(context) } 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 905e377..5455ad9 100644 --- a/app/src/main/java/org/nsh07/pomodoro/ui/AppScreen.kt +++ b/app/src/main/java/org/nsh07/pomodoro/ui/AppScreen.kt @@ -41,8 +41,10 @@ import androidx.compose.material3.Text import androidx.compose.material3.adaptive.currentWindowAdaptiveInfo import androidx.compose.runtime.Composable import androidx.compose.runtime.getValue +import androidx.compose.runtime.mutableStateOf import androidx.compose.runtime.remember import androidx.compose.runtime.rememberUpdatedState +import androidx.compose.runtime.setValue import androidx.compose.ui.Modifier import androidx.compose.ui.platform.LocalContext import androidx.compose.ui.platform.LocalLayoutDirection @@ -54,6 +56,7 @@ import androidx.navigation3.runtime.entryProvider import androidx.navigation3.runtime.rememberNavBackStack import androidx.navigation3.ui.NavDisplay import androidx.window.core.layout.WindowSizeClass +import org.nsh07.pomodoro.billing.TomatoPlusPaywallDialog import org.nsh07.pomodoro.service.TimerService import org.nsh07.pomodoro.ui.settingsScreen.SettingsScreenRoot import org.nsh07.pomodoro.ui.statsScreen.StatsScreenRoot @@ -65,10 +68,11 @@ import org.nsh07.pomodoro.ui.timerScreen.viewModel.TimerViewModel @OptIn(ExperimentalMaterial3Api::class, ExperimentalMaterial3ExpressiveApi::class) @Composable fun AppScreen( - modifier: Modifier = Modifier, - timerViewModel: TimerViewModel = viewModel(factory = TimerViewModel.Factory), isAODEnabled: Boolean, - setTimerFrequency: (Float) -> Unit + isPlus: Boolean, + setTimerFrequency: (Float) -> Unit, + modifier: Modifier = Modifier, + timerViewModel: TimerViewModel = viewModel(factory = TimerViewModel.Factory) ) { val context = LocalContext.current @@ -91,6 +95,7 @@ fun AppScreen( } } + var showPaywall by remember { mutableStateOf(false) } Scaffold( bottomBar = { @@ -218,6 +223,7 @@ fun AppScreen( entry { SettingsScreenRoot( + setShowPaywall = { showPaywall = it }, modifier = modifier.padding( start = contentPadding.calculateStartPadding(layoutDirection), end = contentPadding.calculateEndPadding(layoutDirection), @@ -240,4 +246,5 @@ fun AppScreen( ) } } + if (showPaywall) TomatoPlusPaywallDialog(isPlus = isPlus) { showPaywall = false } } \ No newline at end of file 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 a22b1f5..356c922 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 @@ -17,6 +17,7 @@ package org.nsh07.pomodoro.ui.settingsScreen +import android.annotation.SuppressLint import android.content.Intent import android.net.Uri import androidx.compose.animation.fadeIn @@ -25,19 +26,26 @@ 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 @@ -50,6 +58,7 @@ 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 @@ -80,6 +89,7 @@ import org.nsh07.pomodoro.ui.theme.CustomColors.topBarColors @OptIn(ExperimentalMaterial3Api::class) @Composable fun SettingsScreenRoot( + setShowPaywall: (Boolean) -> Unit, modifier: Modifier = Modifier, viewModel: SettingsViewModel = viewModel(factory = SettingsViewModel.Factory) ) { @@ -102,6 +112,7 @@ fun SettingsScreenRoot( viewModel.longBreakTimeTextFieldState } + val isPlus by viewModel.isPlus.collectAsStateWithLifecycle() val alarmEnabled by viewModel.alarmEnabled.collectAsStateWithLifecycle(true) val vibrateEnabled by viewModel.vibrateEnabled.collectAsStateWithLifecycle(true) val dndEnabled by viewModel.dndEnabled.collectAsStateWithLifecycle(false) @@ -119,6 +130,7 @@ fun SettingsScreenRoot( } SettingsScreen( + isPlus = isPlus, preferencesState = preferencesState, backStack = backStack, focusTimeInputFieldState = focusTimeInputFieldState, @@ -143,13 +155,16 @@ fun SettingsScreenRoot( }, onThemeChange = viewModel::saveTheme, onColorSchemeChange = viewModel::saveColorScheme, + setShowPaywall = setShowPaywall, modifier = modifier ) } +@SuppressLint("LocalContextGetResourceValueCall") @OptIn(ExperimentalMaterial3Api::class, ExperimentalMaterial3ExpressiveApi::class) @Composable private fun SettingsScreen( + isPlus: Boolean, preferencesState: PreferencesState, backStack: SnapshotStateList, focusTimeInputFieldState: TextFieldState, @@ -168,6 +183,7 @@ private fun SettingsScreen( onAlarmSoundChanged: (Uri?) -> Unit, onThemeChange: (String) -> Unit, onColorSchemeChange: (Color) -> Unit, + setShowPaywall: (Boolean) -> Unit, modifier: Modifier = Modifier ) { val context = LocalContext.current @@ -217,6 +233,39 @@ private fun SettingsScreen( ) { item { Spacer(Modifier.height(12.dp)) } + if (!isPlus) 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( + "Get Tomato+", + style = typography.titleLarge, + fontFamily = robotoFlexTopBar, + color = colorScheme.onPrimary + ) + Spacer(Modifier.weight(1f)) + Icon( + painterResource(R.drawable.arrow_forward_big), + null, + tint = colorScheme.onPrimary + ) + } + Spacer(Modifier.height(14.dp)) + } + item { AboutCard() } item { Spacer(Modifier.height(12.dp)) } diff --git a/app/src/main/java/org/nsh07/pomodoro/ui/settingsScreen/viewModel/SettingsViewModel.kt b/app/src/main/java/org/nsh07/pomodoro/ui/settingsScreen/viewModel/SettingsViewModel.kt index 0a3262f..6f9041d 100644 --- a/app/src/main/java/org/nsh07/pomodoro/ui/settingsScreen/viewModel/SettingsViewModel.kt +++ b/app/src/main/java/org/nsh07/pomodoro/ui/settingsScreen/viewModel/SettingsViewModel.kt @@ -40,17 +40,21 @@ import kotlinx.coroutines.flow.distinctUntilChanged import kotlinx.coroutines.flow.update import kotlinx.coroutines.launch import org.nsh07.pomodoro.TomatoApplication +import org.nsh07.pomodoro.billing.BillingManager import org.nsh07.pomodoro.data.AppPreferenceRepository import org.nsh07.pomodoro.data.TimerRepository import org.nsh07.pomodoro.ui.Screen @OptIn(FlowPreview::class, ExperimentalMaterial3Api::class) class SettingsViewModel( + private val billingManager: BillingManager, private val preferenceRepository: AppPreferenceRepository, private val timerRepository: TimerRepository, ) : ViewModel() { val backStack = mutableStateListOf(Screen.Settings.Main) + val isPlus = billingManager.isPlus + private val _preferencesState = MutableStateFlow(PreferencesState()) val preferencesState = _preferencesState.asStateFlow() @@ -237,8 +241,10 @@ class SettingsViewModel( val application = (this[APPLICATION_KEY] as TomatoApplication) val appPreferenceRepository = application.container.appPreferenceRepository val appTimerRepository = application.container.appTimerRepository + val appBillingManager = application.container.billingManager SettingsViewModel( + billingManager = appBillingManager, preferenceRepository = appPreferenceRepository, timerRepository = appTimerRepository, ) diff --git a/app/src/play/java/org/nsh07/pomodoro/billing/PlayBillingManager.kt b/app/src/play/java/org/nsh07/pomodoro/billing/PlayBillingManager.kt new file mode 100644 index 0000000..94bfcb2 --- /dev/null +++ b/app/src/play/java/org/nsh07/pomodoro/billing/PlayBillingManager.kt @@ -0,0 +1,58 @@ +/* + * 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.billing + +import android.util.Log +import com.revenuecat.purchases.Purchases +import com.revenuecat.purchases.getCustomerInfoWith +import com.revenuecat.purchases.interfaces.UpdatedCustomerInfoListener +import kotlinx.coroutines.flow.MutableStateFlow +import kotlinx.coroutines.flow.asStateFlow + +private const val ENTITLEMENT_ID = "plus" + +/** + * Google Play implementation of BillingManager + */ +class PlayBillingManager : BillingManager { + private val _isPlus = MutableStateFlow(false) + override val isPlus = _isPlus.asStateFlow() + + private val purchases by lazy { Purchases.sharedInstance } + + init { + purchases.updatedCustomerInfoListener = + UpdatedCustomerInfoListener { customerInfo -> + _isPlus.value = customerInfo.entitlements[ENTITLEMENT_ID]?.isActive == true + } + + // Fetch initial customer info + purchases.getCustomerInfoWith( + onSuccess = { customerInfo -> + _isPlus.value = customerInfo.entitlements[ENTITLEMENT_ID]?.isActive == true + }, + onError = { error -> + Log.e("GooglePlayPaywallManager", "Error fetching customer info: $error") + } + ) + } +} + +object BillingManagerProvider { + val manager: BillingManager = PlayBillingManager() +} \ No newline at end of file diff --git a/app/src/play/java/org/nsh07/pomodoro/billing/TomatoPlusPaywallDialog.kt b/app/src/play/java/org/nsh07/pomodoro/billing/TomatoPlusPaywallDialog.kt new file mode 100644 index 0000000..1ecda02 --- /dev/null +++ b/app/src/play/java/org/nsh07/pomodoro/billing/TomatoPlusPaywallDialog.kt @@ -0,0 +1,63 @@ +/* + * 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.billing + +import androidx.compose.foundation.layout.padding +import androidx.compose.material3.FilledTonalIconButton +import androidx.compose.material3.Icon +import androidx.compose.material3.Scaffold +import androidx.compose.runtime.Composable +import androidx.compose.runtime.remember +import androidx.compose.ui.Modifier +import androidx.compose.ui.res.painterResource +import androidx.compose.ui.unit.dp +import com.revenuecat.purchases.ui.revenuecatui.Paywall +import com.revenuecat.purchases.ui.revenuecatui.PaywallOptions +import com.revenuecat.purchases.ui.revenuecatui.customercenter.CustomerCenter +import org.nsh07.pomodoro.R + +@Composable +fun TomatoPlusPaywallDialog( + isPlus: Boolean, + onDismiss: () -> Unit +) { + val paywallOptions = remember { + PaywallOptions.Builder(dismissRequest = onDismiss) + .build() + } + + Scaffold { innerPadding -> + if (!isPlus) { + Paywall(paywallOptions) + + FilledTonalIconButton( + onClick = onDismiss, + modifier = Modifier + .padding(innerPadding) + .padding(16.dp) + ) { + Icon( + painterResource(R.drawable.arrow_back), + null + ) + } + } else { + CustomerCenter(onDismiss = onDismiss) + } + } +} \ No newline at end of file diff --git a/app/src/play/java/org/nsh07/pomodoro/billing/initializePurchases.kt b/app/src/play/java/org/nsh07/pomodoro/billing/initializePurchases.kt new file mode 100644 index 0000000..00e2437 --- /dev/null +++ b/app/src/play/java/org/nsh07/pomodoro/billing/initializePurchases.kt @@ -0,0 +1,30 @@ +/* + * 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.billing + +import android.content.Context +import com.revenuecat.purchases.Purchases +import com.revenuecat.purchases.PurchasesConfiguration + +fun initializePurchases(context: Context) { + Purchases.configure( + PurchasesConfiguration + .Builder(context, "goog_jBpRIBjTYvhKYluCqkPXSHbuFbX") + .build() + ) +} \ No newline at end of file diff --git a/gradle/libs.versions.toml b/gradle/libs.versions.toml index 9356ceb..85f21bf 100644 --- a/gradle/libs.versions.toml +++ b/gradle/libs.versions.toml @@ -12,7 +12,7 @@ ksp = "2.2.20-2.0.4" lifecycleRuntimeKtx = "2.9.4" materialKolor = "3.0.1" navigation3 = "1.0.0-beta01" -purchases = "9.12.0" +revenuecat = "9.12.0" room = "2.8.3" vico = "2.2.1" @@ -40,7 +40,8 @@ androidx-ui-tooling = { group = "androidx.compose.ui", name = "ui-tooling" } androidx-ui-tooling-preview = { group = "androidx.compose.ui", name = "ui-tooling-preview" } junit = { group = "junit", name = "junit", version.ref = "junit" } material-kolor = { module = "com.materialkolor:material-kolor", version.ref = "materialKolor" } -purchases = { module = "com.revenuecat.purchases:purchases", version.ref = "purchases" } +revenuecat-purchases = { module = "com.revenuecat.purchases:purchases", version.ref = "revenuecat" } +revenuecat-purchases-ui = { module = "com.revenuecat.purchases:purchases-ui", version.ref = "revenuecat" } vico-compose-m3 = { group = "com.patrykandpatrick.vico", name = "compose-m3", version.ref = "vico" } [plugins] From 86bb382f4b645d2b556f1f09ea821884ca882034 Mon Sep 17 00:00:00 2001 From: Nishant Mishra Date: Mon, 27 Oct 2025 12:13:53 +0530 Subject: [PATCH 14/25] feat(billing): add font for billing screen, add animation --- app/src/main/java/org/nsh07/pomodoro/ui/AppScreen.kt | 11 ++++++++++- .../pomodoro/ui/settingsScreen/SettingsScreen.kt | 5 +++-- app/src/main/res/values/strings.xml | 2 ++ .../nsh07/pomodoro/billing/TomatoPlusPaywallDialog.kt | 3 +-- app/src/play/res/font/roboto_flex.ttf | 0 5 files changed, 16 insertions(+), 5 deletions(-) create mode 100644 app/src/play/res/font/roboto_flex.ttf 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 5455ad9..b7cab88 100644 --- a/app/src/main/java/org/nsh07/pomodoro/ui/AppScreen.kt +++ b/app/src/main/java/org/nsh07/pomodoro/ui/AppScreen.kt @@ -23,6 +23,8 @@ import androidx.compose.animation.Crossfade import androidx.compose.animation.SharedTransitionLayout import androidx.compose.animation.fadeIn import androidx.compose.animation.fadeOut +import androidx.compose.animation.slideInVertically +import androidx.compose.animation.slideOutVertically import androidx.compose.animation.togetherWith import androidx.compose.foundation.clickable import androidx.compose.foundation.layout.calculateEndPadding @@ -246,5 +248,12 @@ fun AppScreen( ) } } - if (showPaywall) TomatoPlusPaywallDialog(isPlus = isPlus) { showPaywall = false } + + AnimatedVisibility( + showPaywall, + enter = slideInVertically { it }, + exit = slideOutVertically { it } + ) { + TomatoPlusPaywallDialog(isPlus = isPlus) { showPaywall = false } + } } \ No newline at end of file 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 356c922..00b2de8 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 @@ -233,7 +233,7 @@ private fun SettingsScreen( ) { item { Spacer(Modifier.height(12.dp)) } - if (!isPlus) item { + item { Row( verticalAlignment = Alignment.CenterVertically, modifier = Modifier @@ -251,7 +251,8 @@ private fun SettingsScreen( ) Spacer(Modifier.width(8.dp)) Text( - "Get Tomato+", + if (!isPlus) stringResource(R.string.get_plus) + else stringResource(R.string.app_name_plus), style = typography.titleLarge, fontFamily = robotoFlexTopBar, color = colorScheme.onPrimary diff --git a/app/src/main/res/values/strings.xml b/app/src/main/res/values/strings.xml index f4c25b8..a71a0b4 100644 --- a/app/src/main/res/values/strings.xml +++ b/app/src/main/res/values/strings.xml @@ -81,4 +81,6 @@ Sound Do Not Disturb Turn on DND when running a Focus timer + Tomato+ + Get Tomato+ \ No newline at end of file diff --git a/app/src/play/java/org/nsh07/pomodoro/billing/TomatoPlusPaywallDialog.kt b/app/src/play/java/org/nsh07/pomodoro/billing/TomatoPlusPaywallDialog.kt index 1ecda02..bd7b318 100644 --- a/app/src/play/java/org/nsh07/pomodoro/billing/TomatoPlusPaywallDialog.kt +++ b/app/src/play/java/org/nsh07/pomodoro/billing/TomatoPlusPaywallDialog.kt @@ -37,8 +37,7 @@ fun TomatoPlusPaywallDialog( onDismiss: () -> Unit ) { val paywallOptions = remember { - PaywallOptions.Builder(dismissRequest = onDismiss) - .build() + PaywallOptions.Builder(dismissRequest = onDismiss).build() } Scaffold { innerPadding -> diff --git a/app/src/play/res/font/roboto_flex.ttf b/app/src/play/res/font/roboto_flex.ttf new file mode 100644 index 0000000..e69de29 From 36960c6c8c209886e43cb44f2664fe831273d5a9 Mon Sep 17 00:00:00 2001 From: Hosted Weblate Date: Mon, 27 Oct 2025 14:02:59 +0100 Subject: [PATCH 15/25] Translated using Weblate (Turkish) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Currently translated at 100.0% (65 of 65 strings) Translated using Weblate (French) Currently translated at 100.0% (65 of 65 strings) Translated using Weblate (German) Currently translated at 100.0% (65 of 65 strings) Translated using Weblate (Chinese (Simplified Han script)) Currently translated at 100.0% (65 of 65 strings) Translated using Weblate (Ukrainian) Currently translated at 100.0% (65 of 65 strings) Co-authored-by: Clyde Johanson Co-authored-by: Elias Frey Co-authored-by: Loïc de Porcaro Co-authored-by: Oğuz Ersen Co-authored-by: vintagezero Translate-URL: https://hosted.weblate.org/projects/tomato/strings/de/ Translate-URL: https://hosted.weblate.org/projects/tomato/strings/fr/ Translate-URL: https://hosted.weblate.org/projects/tomato/strings/tr/ Translate-URL: https://hosted.weblate.org/projects/tomato/strings/uk/ Translate-URL: https://hosted.weblate.org/projects/tomato/strings/zh_Hans/ Translation: Tomato/Strings --- app/src/main/res/values-de/strings.xml | 2 ++ app/src/main/res/values-fr/strings.xml | 13 +++++++++---- app/src/main/res/values-tr/strings.xml | 5 ++++- app/src/main/res/values-uk/strings.xml | 2 ++ app/src/main/res/values-zh-rCN/strings.xml | 4 ++-- 5 files changed, 19 insertions(+), 7 deletions(-) diff --git a/app/src/main/res/values-de/strings.xml b/app/src/main/res/values-de/strings.xml index 789de99..4f8636e 100644 --- a/app/src/main/res/values-de/strings.xml +++ b/app/src/main/res/values-de/strings.xml @@ -62,4 +62,6 @@ Aussehen Dauer Sound + Bitte nicht stören + ‚Bitte nicht stören‘ aktivieren, wenn ein Fokus-Timer läuft diff --git a/app/src/main/res/values-fr/strings.xml b/app/src/main/res/values-fr/strings.xml index 60b8b1d..4ae182d 100644 --- a/app/src/main/res/values-fr/strings.xml +++ b/app/src/main/res/values-fr/strings.xml @@ -1,7 +1,7 @@ Démarrer - Arrêter + Pause Concentration Pause courte Pause longue @@ -18,7 +18,7 @@ Thème de couleurs Dynamique Couleur - Valeur par défaut du système + Système Alarme Clair Sombre @@ -29,7 +29,7 @@ Thème noir Utiliser un thème sombre noir pur Faire sonner l’alarme à la fin du minuteur - Vibrer + Vibration Faire vibrer à la fin du minuteur Thème Paramètres @@ -38,7 +38,7 @@ Une \"session\" est une séquence d’intervalles Pomodoro comprenant des phases de concentration, des pauses courtes et une pause longue. La dernière pause d’une session est toujours une pause longue. Statistiques Aujourd\'hui - Pause + Pauses 7 derniers jours concentration moyenne par jour Plus d\'infos @@ -59,4 +59,9 @@ 12 derniers mois Appuyez n\'importe où lors de l\'affichage du minuteur pour passer en mode AOD Affichage Permanent + Apparence + Durées + Son + Ne pas déranger + Activer le mode ne pas déranger pendant un minuteur de concentration diff --git a/app/src/main/res/values-tr/strings.xml b/app/src/main/res/values-tr/strings.xml index a06754d..e4d397e 100644 --- a/app/src/main/res/values-tr/strings.xml +++ b/app/src/main/res/values-tr/strings.xml @@ -18,7 +18,7 @@ Renk şeması Dinamik Renk - Sistem varsayılanı + Sistem Açık Koyu Tema seçin @@ -61,4 +61,7 @@ Zamanlayıcıyı görüntülerken AOD moduna geçmek için herhangi bir yere dokunun Görünüm Süreler + Ses + Rahatsız Etmeyin + Odaklanma sayacı çalışırken RE\'yi aç diff --git a/app/src/main/res/values-uk/strings.xml b/app/src/main/res/values-uk/strings.xml index 73a30fe..18260d7 100644 --- a/app/src/main/res/values-uk/strings.xml +++ b/app/src/main/res/values-uk/strings.xml @@ -62,4 +62,6 @@ Вигляд Тривалість Звук + Не турбувати + Активувати режим «Не турбувати», доки таймер активний diff --git a/app/src/main/res/values-zh-rCN/strings.xml b/app/src/main/res/values-zh-rCN/strings.xml index 8ea12ee..53dfcb2 100644 --- a/app/src/main/res/values-zh-rCN/strings.xml +++ b/app/src/main/res/values-zh-rCN/strings.xml @@ -62,6 +62,6 @@ 外观 时长 声音 - 勿扰 - 运行“专注”计时器时打开勿扰 + 勿扰模式 + 运行「专注」计时器时打开勿扰 From 540b941b23ae37229a914ac6a59d8752db4ee6f2 Mon Sep 17 00:00:00 2001 From: Nishant Mishra Date: Mon, 27 Oct 2025 19:06:00 +0530 Subject: [PATCH 16/25] fix(billing): remove font to reduce install size --- app/src/play/res/font/roboto_flex.ttf | 0 1 file changed, 0 insertions(+), 0 deletions(-) delete mode 100644 app/src/play/res/font/roboto_flex.ttf diff --git a/app/src/play/res/font/roboto_flex.ttf b/app/src/play/res/font/roboto_flex.ttf deleted file mode 100644 index e69de29..0000000 From a985e8d0fc7eda2e48318d8c0f515d3ce274988e Mon Sep 17 00:00:00 2001 From: Nishant Mishra Date: Mon, 27 Oct 2025 20:27:09 +0530 Subject: [PATCH 17/25] 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 }, {} ) From e4421ffdacb7eacf7321a73df302dba640fa6bcd Mon Sep 17 00:00:00 2001 From: Nishant Mishra Date: Mon, 27 Oct 2025 20:45:16 +0530 Subject: [PATCH 18/25] feat(settings): reorder appearance settings, move strings to res Closes: #97 --- .../components/ColorSchemePickerListItem.kt | 95 +++++++++++-------- .../screens/AppearanceSettings.kt | 35 +++---- app/src/main/res/values/strings.xml | 2 + 3 files changed, 76 insertions(+), 56 deletions(-) diff --git a/app/src/main/java/org/nsh07/pomodoro/ui/settingsScreen/components/ColorSchemePickerListItem.kt b/app/src/main/java/org/nsh07/pomodoro/ui/settingsScreen/components/ColorSchemePickerListItem.kt index 03549b3..2587400 100644 --- a/app/src/main/java/org/nsh07/pomodoro/ui/settingsScreen/components/ColorSchemePickerListItem.kt +++ b/app/src/main/java/org/nsh07/pomodoro/ui/settingsScreen/components/ColorSchemePickerListItem.kt @@ -17,6 +17,7 @@ package org.nsh07.pomodoro.ui.settingsScreen.components +import android.os.Build import androidx.compose.animation.AnimatedContent import androidx.compose.foundation.background import androidx.compose.foundation.layout.Arrangement @@ -28,6 +29,8 @@ import androidx.compose.foundation.layout.padding import androidx.compose.foundation.layout.size import androidx.compose.foundation.lazy.LazyRow import androidx.compose.foundation.lazy.items +import androidx.compose.foundation.shape.CornerSize +import androidx.compose.foundation.shape.RoundedCornerShape import androidx.compose.material3.ExperimentalMaterial3ExpressiveApi import androidx.compose.material3.Icon import androidx.compose.material3.IconButton @@ -38,6 +41,7 @@ import androidx.compose.material3.Switch import androidx.compose.material3.SwitchDefaults import androidx.compose.material3.Text import androidx.compose.runtime.Composable +import androidx.compose.runtime.remember import androidx.compose.ui.Modifier import androidx.compose.ui.draw.clip import androidx.compose.ui.graphics.Color @@ -65,6 +69,7 @@ fun ColorSchemePickerListItem( Color(0xff9fd75c), Color(0xffc1d02d), Color(0xfffabd00), Color(0xffffb86e), Color.White ) + val zeroCorner = remember { CornerSize(0) } Column( modifier @@ -76,45 +81,48 @@ fun ColorSchemePickerListItem( } ) ) { - ListItem( - leadingContent = { - Icon( - painterResource(R.drawable.colors), - null - ) - }, - headlineContent = { Text("Dynamic color") }, - supportingContent = { Text("Adapt theme colors from your wallpaper") }, - trailingContent = { - val checked = color == colorSchemes.last() - Switch( - checked = checked, - onCheckedChange = { - if (it) onColorChange(colorSchemes.last()) - else onColorChange(colorSchemes.first()) - }, - thumbContent = { - if (checked) { - Icon( - painter = painterResource(R.drawable.check), - contentDescription = null, - modifier = Modifier.size(SwitchDefaults.IconSize), - ) - } else { - Icon( - painter = painterResource(R.drawable.clear), - contentDescription = null, - modifier = Modifier.size(SwitchDefaults.IconSize), - ) - } - }, - colors = switchColors - ) - }, - colors = listItemColors, - modifier = Modifier.clip(middleListItemShape) - ) - Spacer(Modifier.height(2.dp)) + if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.S) { + ListItem( + leadingContent = { + Icon( + painterResource(R.drawable.colors), + null + ) + }, + headlineContent = { Text(stringResource(R.string.dynamic_color)) }, + supportingContent = { Text(stringResource(R.string.dynamic_color_desc)) }, + trailingContent = { + val checked = color == colorSchemes.last() + Switch( + checked = checked, + onCheckedChange = { + if (it) onColorChange(colorSchemes.last()) + else onColorChange(colorSchemes.first()) + }, + thumbContent = { + if (checked) { + Icon( + painter = painterResource(R.drawable.check), + contentDescription = null, + modifier = Modifier.size(SwitchDefaults.IconSize), + ) + } else { + Icon( + painter = painterResource(R.drawable.clear), + contentDescription = null, + modifier = Modifier.size(SwitchDefaults.IconSize), + ) + } + }, + colors = switchColors + ) + }, + colors = listItemColors, + modifier = Modifier.clip(middleListItemShape) + ) + Spacer(Modifier.height(2.dp)) + } + ListItem( leadingContent = { Icon( @@ -131,7 +139,14 @@ fun ColorSchemePickerListItem( ) }, colors = listItemColors, - modifier = Modifier.clip(middleListItemShape) + modifier = Modifier.clip( + RoundedCornerShape( + topStart = middleListItemShape.topStart, + topEnd = middleListItemShape.topEnd, + zeroCorner, + zeroCorner + ) + ) ) Column( diff --git a/app/src/main/java/org/nsh07/pomodoro/ui/settingsScreen/screens/AppearanceSettings.kt b/app/src/main/java/org/nsh07/pomodoro/ui/settingsScreen/screens/AppearanceSettings.kt index eb55fb8..e4f44bf 100644 --- a/app/src/main/java/org/nsh07/pomodoro/ui/settingsScreen/screens/AppearanceSettings.kt +++ b/app/src/main/java/org/nsh07/pomodoro/ui/settingsScreen/screens/AppearanceSettings.kt @@ -56,6 +56,7 @@ import org.nsh07.pomodoro.ui.theme.CustomColors.switchColors import org.nsh07.pomodoro.ui.theme.CustomColors.topBarColors import org.nsh07.pomodoro.ui.theme.TomatoShapeDefaults.bottomListItemShape import org.nsh07.pomodoro.ui.theme.TomatoShapeDefaults.middleListItemShape +import org.nsh07.pomodoro.ui.theme.TomatoTheme import org.nsh07.pomodoro.utils.toColor @OptIn(ExperimentalMaterial3Api::class, ExperimentalMaterial3ExpressiveApi::class) @@ -100,24 +101,24 @@ fun AppearanceSettings( item { Spacer(Modifier.height(14.dp)) } - item { - ColorSchemePickerListItem( - color = preferencesState.colorScheme.toColor(), - items = 3, - index = 0, - onColorChange = onColorSchemeChange - ) - } item { ThemePickerListItem( theme = preferencesState.theme, onThemeChange = onThemeChange, items = 3, - index = 1, + index = 0, modifier = Modifier .clip(middleListItemShape) ) } + item { + ColorSchemePickerListItem( + color = preferencesState.colorScheme.toColor(), + items = 3, + index = 1, + onColorChange = onColorSchemeChange + ) + } item { val item = SettingsSwitchItem( checked = preferencesState.blackTheme, @@ -168,11 +169,13 @@ fun AppearanceSettings( @Composable fun AppearanceSettingsPreview() { val preferencesState = PreferencesState() - AppearanceSettings( - preferencesState = preferencesState, - onBlackThemeChange = {}, - onThemeChange = {}, - onColorSchemeChange = {}, - onBack = {} - ) + TomatoTheme { + AppearanceSettings( + preferencesState = preferencesState, + onBlackThemeChange = {}, + onThemeChange = {}, + onColorSchemeChange = {}, + onBack = {} + ) + } } diff --git a/app/src/main/res/values/strings.xml b/app/src/main/res/values/strings.xml index a71a0b4..d03d14c 100644 --- a/app/src/main/res/values/strings.xml +++ b/app/src/main/res/values/strings.xml @@ -83,4 +83,6 @@ Turn on DND when running a Focus timer Tomato+ Get Tomato+ + Dynamic color + Adapt theme colors from your wallpaper \ No newline at end of file From c8d4114db54280f189d0130494196a8c610c945e Mon Sep 17 00:00:00 2001 From: Nishant Mishra Date: Mon, 27 Oct 2025 21:15:09 +0530 Subject: [PATCH 19/25] feat(settings): add paywall restriction in Appearance settings --- .../billing/TomatoPlusPaywallDialog.kt | 5 +- .../ui/settingsScreen/SettingsScreen.kt | 2 + .../components/ColorSchemePickerListItem.kt | 32 +++++++----- .../settingsScreen/components/PlusDivider.kt | 51 +++++++++++++++++++ .../components/ThemePickerListItem.kt | 13 +++-- .../screens/AppearanceSettings.kt | 23 ++++++--- app/src/main/res/values/strings.xml | 2 + 7 files changed, 101 insertions(+), 27 deletions(-) create mode 100644 app/src/main/java/org/nsh07/pomodoro/ui/settingsScreen/components/PlusDivider.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 e406f57..6df4870 100644 --- a/app/src/foss/java/org/nsh07/pomodoro/billing/TomatoPlusPaywallDialog.kt +++ b/app/src/foss/java/org/nsh07/pomodoro/billing/TomatoPlusPaywallDialog.kt @@ -35,6 +35,7 @@ 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.res.stringResource import androidx.compose.ui.text.style.TextAlign import androidx.compose.ui.unit.dp import org.nsh07.pomodoro.R @@ -63,14 +64,14 @@ fun TomatoPlusPaywallDialog( ) Spacer(Modifier.height(16.dp)) Text( - "Tomato FOSS", + stringResource(R.string.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"}.", + stringResource(R.string.tomato_foss_desc, "BuyMeACoffee"), textAlign = TextAlign.Center, color = colorScheme.onSurfaceVariant, modifier = Modifier.padding(horizontal = 24.dp) 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 af64b04..2d6243a 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 @@ -285,9 +285,11 @@ private fun SettingsScreen( entry { AppearanceSettings( preferencesState = preferencesState, + isPlus = isPlus, onBlackThemeChange = onBlackThemeChange, onThemeChange = onThemeChange, onColorSchemeChange = onColorSchemeChange, + setShowPaywall = setShowPaywall, onBack = backStack::removeLastOrNull ) } diff --git a/app/src/main/java/org/nsh07/pomodoro/ui/settingsScreen/components/ColorSchemePickerListItem.kt b/app/src/main/java/org/nsh07/pomodoro/ui/settingsScreen/components/ColorSchemePickerListItem.kt index 2587400..095ffec 100644 --- a/app/src/main/java/org/nsh07/pomodoro/ui/settingsScreen/components/ColorSchemePickerListItem.kt +++ b/app/src/main/java/org/nsh07/pomodoro/ui/settingsScreen/components/ColorSchemePickerListItem.kt @@ -20,7 +20,6 @@ package org.nsh07.pomodoro.ui.settingsScreen.components import android.os.Build import androidx.compose.animation.AnimatedContent import androidx.compose.foundation.background -import androidx.compose.foundation.layout.Arrangement import androidx.compose.foundation.layout.Column import androidx.compose.foundation.layout.PaddingValues import androidx.compose.foundation.layout.Spacer @@ -60,6 +59,7 @@ fun ColorSchemePickerListItem( color: Color, items: Int, index: Int, + isPlus: Boolean, onColorChange: (Color) -> Unit, modifier: Modifier = Modifier ) { @@ -99,6 +99,7 @@ fun ColorSchemePickerListItem( if (it) onColorChange(colorSchemes.last()) else onColorChange(colorSchemes.first()) }, + enabled = isPlus, thumbContent = { if (checked) { Icon( @@ -149,21 +150,21 @@ fun ColorSchemePickerListItem( ) ) - Column( - verticalArrangement = Arrangement.spacedBy(8.dp), + LazyRow( + contentPadding = PaddingValues(horizontal = 48.dp), + userScrollEnabled = isPlus, modifier = Modifier .background(listItemColors.containerColor) .padding(bottom = 8.dp) ) { - LazyRow(contentPadding = PaddingValues(horizontal = 48.dp)) { - items(colorSchemes.dropLast(1)) { - ColorPickerButton( - it, - it == color, - modifier = Modifier.padding(4.dp) - ) { - onColorChange(it) - } + items(colorSchemes.dropLast(1)) { + ColorPickerButton( + color = it, + isSelected = it == color, + enabled = isPlus, + modifier = Modifier.padding(4.dp) + ) { + onColorChange(it) } } } @@ -175,12 +176,17 @@ fun ColorSchemePickerListItem( fun ColorPickerButton( color: Color, isSelected: Boolean, + enabled: Boolean, modifier: Modifier = Modifier, onClick: () -> Unit ) { IconButton( shapes = IconButtonDefaults.shapes(), - colors = IconButtonDefaults.iconButtonColors(containerColor = color), + colors = IconButtonDefaults.iconButtonColors( + containerColor = color, + disabledContainerColor = color.copy(0.3f) + ), + enabled = enabled, modifier = modifier.size(48.dp), onClick = onClick ) { diff --git a/app/src/main/java/org/nsh07/pomodoro/ui/settingsScreen/components/PlusDivider.kt b/app/src/main/java/org/nsh07/pomodoro/ui/settingsScreen/components/PlusDivider.kt new file mode 100644 index 0000000..e950564 --- /dev/null +++ b/app/src/main/java/org/nsh07/pomodoro/ui/settingsScreen/components/PlusDivider.kt @@ -0,0 +1,51 @@ +/* + * 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.layout.Box +import androidx.compose.foundation.layout.padding +import androidx.compose.foundation.shape.CircleShape +import androidx.compose.material3.Button +import androidx.compose.material3.HorizontalDivider +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.unit.dp + +@Composable +fun PlusDivider( + setShowPaywall: (Boolean) -> Unit, + modifier: Modifier = Modifier +) { + Box(contentAlignment = Alignment.Center, modifier = modifier.padding(vertical = 14.dp)) { + HorizontalDivider(modifier = Modifier.clip(CircleShape), thickness = 4.dp) + Button( + onClick = { setShowPaywall(true) }, + modifier = Modifier + .background(colorScheme.surfaceContainer) + .padding(horizontal = 8.dp) + ) { + Text("Customize further with Tomato+", style = typography.titleSmall) + } + } +} \ No newline at end of file diff --git a/app/src/main/java/org/nsh07/pomodoro/ui/settingsScreen/components/ThemePickerListItem.kt b/app/src/main/java/org/nsh07/pomodoro/ui/settingsScreen/components/ThemePickerListItem.kt index 0392765..411de79 100644 --- a/app/src/main/java/org/nsh07/pomodoro/ui/settingsScreen/components/ThemePickerListItem.kt +++ b/app/src/main/java/org/nsh07/pomodoro/ui/settingsScreen/components/ThemePickerListItem.kt @@ -43,6 +43,7 @@ import androidx.compose.ui.unit.dp import org.nsh07.pomodoro.R import org.nsh07.pomodoro.ui.theme.CustomColors.listItemColors import org.nsh07.pomodoro.ui.theme.TomatoShapeDefaults.bottomListItemShape +import org.nsh07.pomodoro.ui.theme.TomatoShapeDefaults.cardShape import org.nsh07.pomodoro.ui.theme.TomatoShapeDefaults.middleListItemShape import org.nsh07.pomodoro.ui.theme.TomatoShapeDefaults.topListItemShape @@ -69,11 +70,13 @@ fun ThemePickerListItem( Column( modifier .clip( - when (index) { - 0 -> topListItemShape - items - 1 -> bottomListItemShape - else -> middleListItemShape - }, + if (items > 1) + when (index) { + 0 -> topListItemShape + items - 1 -> bottomListItemShape + else -> middleListItemShape + } + else cardShape, ), ) { ListItem( diff --git a/app/src/main/java/org/nsh07/pomodoro/ui/settingsScreen/screens/AppearanceSettings.kt b/app/src/main/java/org/nsh07/pomodoro/ui/settingsScreen/screens/AppearanceSettings.kt index e4f44bf..6f6d903 100644 --- a/app/src/main/java/org/nsh07/pomodoro/ui/settingsScreen/screens/AppearanceSettings.kt +++ b/app/src/main/java/org/nsh07/pomodoro/ui/settingsScreen/screens/AppearanceSettings.kt @@ -48,6 +48,7 @@ import androidx.compose.ui.unit.dp import org.nsh07.pomodoro.R import org.nsh07.pomodoro.ui.settingsScreen.SettingsSwitchItem import org.nsh07.pomodoro.ui.settingsScreen.components.ColorSchemePickerListItem +import org.nsh07.pomodoro.ui.settingsScreen.components.PlusDivider import org.nsh07.pomodoro.ui.settingsScreen.components.ThemePickerListItem import org.nsh07.pomodoro.ui.settingsScreen.viewModel.PreferencesState import org.nsh07.pomodoro.ui.theme.AppFonts.robotoFlexTopBar @@ -55,7 +56,6 @@ import org.nsh07.pomodoro.ui.theme.CustomColors.listItemColors import org.nsh07.pomodoro.ui.theme.CustomColors.switchColors import org.nsh07.pomodoro.ui.theme.CustomColors.topBarColors import org.nsh07.pomodoro.ui.theme.TomatoShapeDefaults.bottomListItemShape -import org.nsh07.pomodoro.ui.theme.TomatoShapeDefaults.middleListItemShape import org.nsh07.pomodoro.ui.theme.TomatoTheme import org.nsh07.pomodoro.utils.toColor @@ -63,9 +63,11 @@ import org.nsh07.pomodoro.utils.toColor @Composable fun AppearanceSettings( preferencesState: PreferencesState, + isPlus: Boolean, onBlackThemeChange: (Boolean) -> Unit, onThemeChange: (String) -> Unit, onColorSchemeChange: (Color) -> Unit, + setShowPaywall: (Boolean) -> Unit, onBack: () -> Unit, modifier: Modifier = Modifier ) { @@ -105,18 +107,22 @@ fun AppearanceSettings( ThemePickerListItem( theme = preferencesState.theme, onThemeChange = onThemeChange, - items = 3, - index = 0, - modifier = Modifier - .clip(middleListItemShape) + items = if (isPlus) 3 else 1, + index = 0 ) } + + if (!isPlus) { + item { PlusDivider(setShowPaywall) } + } + item { ColorSchemePickerListItem( color = preferencesState.colorScheme.toColor(), items = 3, - index = 1, - onColorChange = onColorSchemeChange + index = if (isPlus) 1 else 0, + isPlus = isPlus, + onColorChange = onColorSchemeChange, ) } item { @@ -137,6 +143,7 @@ fun AppearanceSettings( Switch( checked = item.checked, onCheckedChange = { item.onClick(it) }, + enabled = isPlus, thumbContent = { if (item.checked) { Icon( @@ -172,9 +179,11 @@ fun AppearanceSettingsPreview() { TomatoTheme { AppearanceSettings( preferencesState = preferencesState, + isPlus = false, onBlackThemeChange = {}, onThemeChange = {}, onColorSchemeChange = {}, + setShowPaywall = {}, onBack = {} ) } diff --git a/app/src/main/res/values/strings.xml b/app/src/main/res/values/strings.xml index d03d14c..79d3d99 100644 --- a/app/src/main/res/values/strings.xml +++ b/app/src/main/res/values/strings.xml @@ -85,4 +85,6 @@ Get Tomato+ Dynamic color Adapt theme colors from your wallpaper + Tomato FOSS + All features are unlocked in this version. If my app made a difference in your life, please consider supporting me by donating on %1$s. \ No newline at end of file From 509bcdab6d2bccd7f22c3e7d705463de2b7b65e2 Mon Sep 17 00:00:00 2001 From: Nishant Mishra Date: Mon, 27 Oct 2025 21:32:37 +0530 Subject: [PATCH 20/25] feat(settings): add paywall restriction in Timer settings --- .../ui/settingsScreen/SettingsScreen.kt | 4 +- .../settingsScreen/screens/TimerSettings.kt | 65 +++++++++++++++++-- 2 files changed, 61 insertions(+), 8 deletions(-) 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 2d6243a..2f8d2dd 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 @@ -295,6 +295,7 @@ private fun SettingsScreen( } entry { TimerSettings( + isPlus = isPlus, aodEnabled = preferencesState.aodEnabled, dndEnabled = dndEnabled, focusTimeInputFieldState = focusTimeInputFieldState, @@ -303,7 +304,8 @@ private fun SettingsScreen( sessionsSliderState = sessionsSliderState, onAodEnabledChange = onAodEnabledChange, onDndEnabledChange = onDndEnabledChange, - onBack = backStack::removeLastOrNull + setShowPaywall = setShowPaywall, + onBack = backStack::removeLastOrNull, ) } } diff --git a/app/src/main/java/org/nsh07/pomodoro/ui/settingsScreen/screens/TimerSettings.kt b/app/src/main/java/org/nsh07/pomodoro/ui/settingsScreen/screens/TimerSettings.kt index 421140c..b0c7ea3 100644 --- a/app/src/main/java/org/nsh07/pomodoro/ui/settingsScreen/screens/TimerSettings.kt +++ b/app/src/main/java/org/nsh07/pomodoro/ui/settingsScreen/screens/TimerSettings.kt @@ -75,6 +75,7 @@ import androidx.compose.ui.unit.dp import org.nsh07.pomodoro.R import org.nsh07.pomodoro.ui.settingsScreen.SettingsSwitchItem import org.nsh07.pomodoro.ui.settingsScreen.components.MinuteInputField +import org.nsh07.pomodoro.ui.settingsScreen.components.PlusDivider import org.nsh07.pomodoro.ui.theme.AppFonts.robotoFlexTopBar import org.nsh07.pomodoro.ui.theme.CustomColors.listItemColors import org.nsh07.pomodoro.ui.theme.CustomColors.switchColors @@ -88,6 +89,7 @@ import org.nsh07.pomodoro.ui.theme.TomatoShapeDefaults.topListItemShape @OptIn(ExperimentalMaterial3Api::class, ExperimentalMaterial3ExpressiveApi::class) @Composable fun TimerSettings( + isPlus: Boolean, aodEnabled: Boolean, dndEnabled: Boolean, focusTimeInputFieldState: TextFieldState, @@ -97,7 +99,8 @@ fun TimerSettings( onAodEnabledChange: (Boolean) -> Unit, onDndEnabledChange: (Boolean) -> Unit, onBack: () -> Unit, - modifier: Modifier = Modifier + modifier: Modifier = Modifier, + setShowPaywall: (Boolean) -> Unit ) { val scrollBehavior = TopAppBarDefaults.enterAlwaysScrollBehavior() val context = LocalContext.current @@ -260,7 +263,8 @@ fun TimerSettings( ) } item { Spacer(Modifier.height(12.dp)) } - itemsIndexed(switchItems) { index, item -> + + itemsIndexed(if (isPlus) switchItems else switchItems.take(1)) { index, item -> ListItem( leadingContent = { Icon( @@ -295,15 +299,60 @@ fun TimerSettings( }, colors = listItemColors, modifier = Modifier.clip( - when (index) { + if (isPlus) when (index) { 0 -> topListItemShape switchItems.size - 1 -> bottomListItemShape else -> middleListItemShape } + else cardShape ) ) } + if (!isPlus) { + item { + PlusDivider(setShowPaywall) + } + itemsIndexed(switchItems.drop(1)) { index, item -> + ListItem( + leadingContent = { + Icon( + painterResource(item.icon), + contentDescription = null, + modifier = Modifier.padding(top = 4.dp) + ) + }, + headlineContent = { Text(stringResource(item.label)) }, + supportingContent = { Text(stringResource(item.description)) }, + trailingContent = { + Switch( + checked = item.checked, + onCheckedChange = { item.onClick(it) }, + enabled = isPlus, + thumbContent = { + if (item.checked) { + Icon( + painter = painterResource(R.drawable.check), + contentDescription = null, + modifier = Modifier.size(SwitchDefaults.IconSize), + ) + } else { + Icon( + painter = painterResource(R.drawable.clear), + contentDescription = null, + modifier = Modifier.size(SwitchDefaults.IconSize), + ) + } + }, + colors = switchColors + ) + }, + colors = listItemColors, + modifier = Modifier.clip(cardShape) + ) + } + } + item { var expanded by remember { mutableStateOf(false) } Column( @@ -352,14 +401,16 @@ private fun TimerSettingsPreview() { steps = 6 ) TimerSettings( + isPlus = false, + aodEnabled = true, + dndEnabled = false, focusTimeInputFieldState = focusTimeInputFieldState, shortBreakTimeInputFieldState = shortBreakTimeInputFieldState, longBreakTimeInputFieldState = longBreakTimeInputFieldState, sessionsSliderState = sessionsSliderState, - aodEnabled = true, - dndEnabled = false, - onBack = {}, onAodEnabledChange = {}, - onDndEnabledChange = {} + onDndEnabledChange = {}, + setShowPaywall = {}, + onBack = {} ) } \ No newline at end of file From de6550d6ab94995eca1ea0b7e81787c2c3d76788 Mon Sep 17 00:00:00 2001 From: Nishant Mishra Date: Tue, 28 Oct 2025 11:01:29 +0530 Subject: [PATCH 21/25] feat(settings): reset settings when subscription expires --- .../pomodoro/billing/FossBillingManager.kt | 1 + .../java/org/nsh07/pomodoro/MainActivity.kt | 12 +++++ .../nsh07/pomodoro/billing/BillingManager.kt | 1 + .../viewModel/SettingsViewModel.kt | 53 +++++++++++++------ .../pomodoro/billing/PlayBillingManager.kt | 5 ++ 5 files changed, 55 insertions(+), 17 deletions(-) diff --git a/app/src/foss/java/org/nsh07/pomodoro/billing/FossBillingManager.kt b/app/src/foss/java/org/nsh07/pomodoro/billing/FossBillingManager.kt index 4a155a3..529b58c 100644 --- a/app/src/foss/java/org/nsh07/pomodoro/billing/FossBillingManager.kt +++ b/app/src/foss/java/org/nsh07/pomodoro/billing/FossBillingManager.kt @@ -25,6 +25,7 @@ import kotlinx.coroutines.flow.asStateFlow */ class FossBillingManager : BillingManager { override val isPlus = MutableStateFlow(true).asStateFlow() + override val isLoaded = MutableStateFlow(true).asStateFlow() } object BillingManagerProvider { diff --git a/app/src/main/java/org/nsh07/pomodoro/MainActivity.kt b/app/src/main/java/org/nsh07/pomodoro/MainActivity.kt index 4f34773..1917159 100644 --- a/app/src/main/java/org/nsh07/pomodoro/MainActivity.kt +++ b/app/src/main/java/org/nsh07/pomodoro/MainActivity.kt @@ -61,6 +61,18 @@ class MainActivity : ComponentActivity() { val seed = preferencesState.colorScheme.toColor() val isPlus by settingsViewModel.isPlus.collectAsStateWithLifecycle() + val isPurchaseStateLoaded by settingsViewModel.isPurchaseStateLoaded.collectAsStateWithLifecycle() + val isSettingsLoaded by settingsViewModel.isSettingsLoaded.collectAsStateWithLifecycle() + + LaunchedEffect(isPurchaseStateLoaded, isPlus, isSettingsLoaded) { + if (isPurchaseStateLoaded && isSettingsLoaded) { + if (!isPlus) { + settingsViewModel.resetPaywalledSettings() + } else { + settingsViewModel.reloadSettings() + } + } + } TomatoTheme( darkTheme = darkTheme, diff --git a/app/src/main/java/org/nsh07/pomodoro/billing/BillingManager.kt b/app/src/main/java/org/nsh07/pomodoro/billing/BillingManager.kt index 66b1659..4cdc106 100644 --- a/app/src/main/java/org/nsh07/pomodoro/billing/BillingManager.kt +++ b/app/src/main/java/org/nsh07/pomodoro/billing/BillingManager.kt @@ -21,4 +21,5 @@ import kotlinx.coroutines.flow.StateFlow interface BillingManager { val isPlus: StateFlow + val isLoaded: StateFlow } \ No newline at end of file diff --git a/app/src/main/java/org/nsh07/pomodoro/ui/settingsScreen/viewModel/SettingsViewModel.kt b/app/src/main/java/org/nsh07/pomodoro/ui/settingsScreen/viewModel/SettingsViewModel.kt index 6f9041d..94ba2c6 100644 --- a/app/src/main/java/org/nsh07/pomodoro/ui/settingsScreen/viewModel/SettingsViewModel.kt +++ b/app/src/main/java/org/nsh07/pomodoro/ui/settingsScreen/viewModel/SettingsViewModel.kt @@ -54,6 +54,10 @@ class SettingsViewModel( val backStack = mutableStateListOf(Screen.Settings.Main) val isPlus = billingManager.isPlus + val isPurchaseStateLoaded = billingManager.isLoaded + + private val _isSettingsLoaded = MutableStateFlow(false) + val isSettingsLoaded = _isSettingsLoaded.asStateFlow() private val _preferencesState = MutableStateFlow(PreferencesState()) val preferencesState = _preferencesState.asStateFlow() @@ -94,23 +98,8 @@ class SettingsViewModel( init { viewModelScope.launch { - val theme = preferenceRepository.getStringPreference("theme") - ?: preferenceRepository.saveStringPreference("theme", "auto") - val colorScheme = preferenceRepository.getStringPreference("color_scheme") - ?: preferenceRepository.saveStringPreference("color_scheme", Color.White.toString()) - val blackTheme = preferenceRepository.getBooleanPreference("black_theme") - ?: preferenceRepository.saveBooleanPreference("black_theme", false) - val aodEnabled = preferenceRepository.getBooleanPreference("aod_enabled") - ?: preferenceRepository.saveBooleanPreference("aod_enabled", false) - - _preferencesState.update { currentState -> - currentState.copy( - theme = theme, - colorScheme = colorScheme, - blackTheme = blackTheme, - aodEnabled = aodEnabled - ) - } + reloadSettings() + _isSettingsLoaded.value = true } } @@ -235,6 +224,36 @@ class SettingsViewModel( } } + fun resetPaywalledSettings() { + _preferencesState.update { currentState -> + currentState.copy( + aodEnabled = false, + blackTheme = false, + colorScheme = Color.White.toString() + ) + } + } + + suspend fun reloadSettings() { + val theme = preferenceRepository.getStringPreference("theme") + ?: preferenceRepository.saveStringPreference("theme", "auto") + val colorScheme = preferenceRepository.getStringPreference("color_scheme") + ?: preferenceRepository.saveStringPreference("color_scheme", Color.White.toString()) + val blackTheme = preferenceRepository.getBooleanPreference("black_theme") + ?: preferenceRepository.saveBooleanPreference("black_theme", false) + val aodEnabled = preferenceRepository.getBooleanPreference("aod_enabled") + ?: preferenceRepository.saveBooleanPreference("aod_enabled", false) + + _preferencesState.update { currentState -> + currentState.copy( + theme = theme, + colorScheme = colorScheme, + blackTheme = blackTheme, + aodEnabled = aodEnabled + ) + } + } + companion object { val Factory: ViewModelProvider.Factory = viewModelFactory { initializer { diff --git a/app/src/play/java/org/nsh07/pomodoro/billing/PlayBillingManager.kt b/app/src/play/java/org/nsh07/pomodoro/billing/PlayBillingManager.kt index 94bfcb2..a658884 100644 --- a/app/src/play/java/org/nsh07/pomodoro/billing/PlayBillingManager.kt +++ b/app/src/play/java/org/nsh07/pomodoro/billing/PlayBillingManager.kt @@ -33,6 +33,9 @@ class PlayBillingManager : BillingManager { private val _isPlus = MutableStateFlow(false) override val isPlus = _isPlus.asStateFlow() + private val _isLoaded = MutableStateFlow(false) + override val isLoaded = _isLoaded.asStateFlow() + private val purchases by lazy { Purchases.sharedInstance } init { @@ -45,9 +48,11 @@ class PlayBillingManager : BillingManager { purchases.getCustomerInfoWith( onSuccess = { customerInfo -> _isPlus.value = customerInfo.entitlements[ENTITLEMENT_ID]?.isActive == true + _isLoaded.value = true }, onError = { error -> Log.e("GooglePlayPaywallManager", "Error fetching customer info: $error") + _isLoaded.value = true } ) } From 43d3118afe51848a0b0ab446b100cc79afd75511 Mon Sep 17 00:00:00 2001 From: Nishant Mishra Date: Tue, 28 Oct 2025 11:38:09 +0530 Subject: [PATCH 22/25] feat(ui): update default theme to match sample screenshots --- .../screens/AppearanceSettings.kt | 2 +- .../java/org/nsh07/pomodoro/ui/theme/Color.kt | 76 +++++++++++- .../java/org/nsh07/pomodoro/ui/theme/Theme.kt | 111 ++++++++++++++---- 3 files changed, 162 insertions(+), 27 deletions(-) diff --git a/app/src/main/java/org/nsh07/pomodoro/ui/settingsScreen/screens/AppearanceSettings.kt b/app/src/main/java/org/nsh07/pomodoro/ui/settingsScreen/screens/AppearanceSettings.kt index 6f6d903..d5a12ff 100644 --- a/app/src/main/java/org/nsh07/pomodoro/ui/settingsScreen/screens/AppearanceSettings.kt +++ b/app/src/main/java/org/nsh07/pomodoro/ui/settingsScreen/screens/AppearanceSettings.kt @@ -176,7 +176,7 @@ fun AppearanceSettings( @Composable fun AppearanceSettingsPreview() { val preferencesState = PreferencesState() - TomatoTheme { + TomatoTheme(dynamicColor = false) { AppearanceSettings( preferencesState = preferencesState, isPlus = false, diff --git a/app/src/main/java/org/nsh07/pomodoro/ui/theme/Color.kt b/app/src/main/java/org/nsh07/pomodoro/ui/theme/Color.kt index 064d7d8..d259777 100644 --- a/app/src/main/java/org/nsh07/pomodoro/ui/theme/Color.kt +++ b/app/src/main/java/org/nsh07/pomodoro/ui/theme/Color.kt @@ -28,13 +28,77 @@ import androidx.compose.material3.TopAppBarDefaults import androidx.compose.runtime.Composable import androidx.compose.ui.graphics.Color -val Purple80 = Color(0xFFD0BCFF) -val PurpleGrey80 = Color(0xFFCCC2DC) -val Pink80 = Color(0xFFEFB8C8) +val primaryLight = Color(0xFF4C662B) +val onPrimaryLight = Color(0xFFFFFFFF) +val primaryContainerLight = Color(0xFFCDEDA3) +val onPrimaryContainerLight = Color(0xFF354E16) +val secondaryLight = Color(0xFF586249) +val onSecondaryLight = Color(0xFFFFFFFF) +val secondaryContainerLight = Color(0xFFDCE7C8) +val onSecondaryContainerLight = Color(0xFF404A33) +val tertiaryLight = Color(0xFF386663) +val onTertiaryLight = Color(0xFFFFFFFF) +val tertiaryContainerLight = Color(0xFFBCECE7) +val onTertiaryContainerLight = Color(0xFF1F4E4B) +val errorLight = Color(0xFFBA1A1A) +val onErrorLight = Color(0xFFFFFFFF) +val errorContainerLight = Color(0xFFFFDAD6) +val onErrorContainerLight = Color(0xFF93000A) +val backgroundLight = Color(0xFFF9FAEF) +val onBackgroundLight = Color(0xFF1A1C16) +val surfaceLight = Color(0xFFF9FAEF) +val onSurfaceLight = Color(0xFF1A1C16) +val surfaceVariantLight = Color(0xFFE1E4D5) +val onSurfaceVariantLight = Color(0xFF44483D) +val outlineLight = Color(0xFF75796C) +val outlineVariantLight = Color(0xFFC5C8BA) +val scrimLight = Color(0xFF000000) +val inverseSurfaceLight = Color(0xFF2F312A) +val inverseOnSurfaceLight = Color(0xFFF1F2E6) +val inversePrimaryLight = Color(0xFFB1D18A) +val surfaceDimLight = Color(0xFFDADBD0) +val surfaceBrightLight = Color(0xFFF9FAEF) +val surfaceContainerLowestLight = Color(0xFFFFFFFF) +val surfaceContainerLowLight = Color(0xFFF3F4E9) +val surfaceContainerLight = Color(0xFFEEEFE3) +val surfaceContainerHighLight = Color(0xFFE8E9DE) +val surfaceContainerHighestLight = Color(0xFFE2E3D8) -val Purple40 = Color(0xFF6650a4) -val PurpleGrey40 = Color(0xFF625b71) -val Pink40 = Color(0xFF7D5260) +val primaryDark = Color(0xFFB1D18A) +val onPrimaryDark = Color(0xFF1F3701) +val primaryContainerDark = Color(0xFF354E16) +val onPrimaryContainerDark = Color(0xFFCDEDA3) +val secondaryDark = Color(0xFFBFCBAD) +val onSecondaryDark = Color(0xFF2A331E) +val secondaryContainerDark = Color(0xFF404A33) +val onSecondaryContainerDark = Color(0xFFDCE7C8) +val tertiaryDark = Color(0xFFA0D0CB) +val onTertiaryDark = Color(0xFF003735) +val tertiaryContainerDark = Color(0xFF1F4E4B) +val onTertiaryContainerDark = Color(0xFFBCECE7) +val errorDark = Color(0xFFFFB4AB) +val onErrorDark = Color(0xFF690005) +val errorContainerDark = Color(0xFF93000A) +val onErrorContainerDark = Color(0xFFFFDAD6) +val backgroundDark = Color(0xFF12140E) +val onBackgroundDark = Color(0xFFE2E3D8) +val surfaceDark = Color(0xFF12140E) +val onSurfaceDark = Color(0xFFE2E3D8) +val surfaceVariantDark = Color(0xFF44483D) +val onSurfaceVariantDark = Color(0xFFC5C8BA) +val outlineDark = Color(0xFF8F9285) +val outlineVariantDark = Color(0xFF44483D) +val scrimDark = Color(0xFF000000) +val inverseSurfaceDark = Color(0xFFE2E3D8) +val inverseOnSurfaceDark = Color(0xFF2F312A) +val inversePrimaryDark = Color(0xFF4C662B) +val surfaceDimDark = Color(0xFF12140E) +val surfaceBrightDark = Color(0xFF383A32) +val surfaceContainerLowestDark = Color(0xFF0C0F09) +val surfaceContainerLowDark = Color(0xFF1A1C16) +val surfaceContainerDark = Color(0xFF1E201A) +val surfaceContainerHighDark = Color(0xFF282B24) +val surfaceContainerHighestDark = Color(0xFF33362E) object CustomColors { var black = false diff --git a/app/src/main/java/org/nsh07/pomodoro/ui/theme/Theme.kt b/app/src/main/java/org/nsh07/pomodoro/ui/theme/Theme.kt index da61be6..e5015f0 100644 --- a/app/src/main/java/org/nsh07/pomodoro/ui/theme/Theme.kt +++ b/app/src/main/java/org/nsh07/pomodoro/ui/theme/Theme.kt @@ -1,3 +1,20 @@ +/* + * 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.theme import android.app.Activity @@ -19,26 +36,80 @@ import androidx.core.view.WindowCompat import com.materialkolor.dynamiccolor.ColorSpec import com.materialkolor.rememberDynamicColorScheme -private val DarkColorScheme = darkColorScheme( - primary = Purple80, - secondary = PurpleGrey80, - tertiary = Pink80 +private val lightScheme = lightColorScheme( + primary = primaryLight, + onPrimary = onPrimaryLight, + primaryContainer = primaryContainerLight, + onPrimaryContainer = onPrimaryContainerLight, + secondary = secondaryLight, + onSecondary = onSecondaryLight, + secondaryContainer = secondaryContainerLight, + onSecondaryContainer = onSecondaryContainerLight, + tertiary = tertiaryLight, + onTertiary = onTertiaryLight, + tertiaryContainer = tertiaryContainerLight, + onTertiaryContainer = onTertiaryContainerLight, + error = errorLight, + onError = onErrorLight, + errorContainer = errorContainerLight, + onErrorContainer = onErrorContainerLight, + background = backgroundLight, + onBackground = onBackgroundLight, + surface = surfaceLight, + onSurface = onSurfaceLight, + surfaceVariant = surfaceVariantLight, + onSurfaceVariant = onSurfaceVariantLight, + outline = outlineLight, + outlineVariant = outlineVariantLight, + scrim = scrimLight, + inverseSurface = inverseSurfaceLight, + inverseOnSurface = inverseOnSurfaceLight, + inversePrimary = inversePrimaryLight, + surfaceDim = surfaceDimLight, + surfaceBright = surfaceBrightLight, + surfaceContainerLowest = surfaceContainerLowestLight, + surfaceContainerLow = surfaceContainerLowLight, + surfaceContainer = surfaceContainerLight, + surfaceContainerHigh = surfaceContainerHighLight, + surfaceContainerHighest = surfaceContainerHighestLight, ) -private val LightColorScheme = lightColorScheme( - primary = Purple40, - secondary = PurpleGrey40, - tertiary = Pink40 - - /* Other default colors to override - background = Color(0xFFFFFBFE), - surface = Color(0xFFFFFBFE), - onPrimary = Color.White, - onSecondary = Color.White, - onTertiary = Color.White, - onBackground = Color(0xFF1C1B1F), - onSurface = Color(0xFF1C1B1F), - */ +private val darkScheme = darkColorScheme( + primary = primaryDark, + onPrimary = onPrimaryDark, + primaryContainer = primaryContainerDark, + onPrimaryContainer = onPrimaryContainerDark, + secondary = secondaryDark, + onSecondary = onSecondaryDark, + secondaryContainer = secondaryContainerDark, + onSecondaryContainer = onSecondaryContainerDark, + tertiary = tertiaryDark, + onTertiary = onTertiaryDark, + tertiaryContainer = tertiaryContainerDark, + onTertiaryContainer = onTertiaryContainerDark, + error = errorDark, + onError = onErrorDark, + errorContainer = errorContainerDark, + onErrorContainer = onErrorContainerDark, + background = backgroundDark, + onBackground = onBackgroundDark, + surface = surfaceDark, + onSurface = onSurfaceDark, + surfaceVariant = surfaceVariantDark, + onSurfaceVariant = onSurfaceVariantDark, + outline = outlineDark, + outlineVariant = outlineVariantDark, + scrim = scrimDark, + inverseSurface = inverseSurfaceDark, + inverseOnSurface = inverseOnSurfaceDark, + inversePrimary = inversePrimaryDark, + surfaceDim = surfaceDimDark, + surfaceBright = surfaceBrightDark, + surfaceContainerLowest = surfaceContainerLowestDark, + surfaceContainerLow = surfaceContainerLowDark, + surfaceContainer = surfaceContainerDark, + surfaceContainerHigh = surfaceContainerHighDark, + surfaceContainerHighest = surfaceContainerHighestDark, ) @OptIn(ExperimentalMaterial3ExpressiveApi::class) @@ -56,8 +127,8 @@ fun TomatoTheme( if (darkTheme) dynamicDarkColorScheme(context) else dynamicLightColorScheme(context) } - darkTheme -> DarkColorScheme - else -> LightColorScheme + darkTheme -> darkScheme + else -> lightScheme } val view = LocalView.current From 9b54d3597c6be0c192cdb33069065d38c1db57a1 Mon Sep 17 00:00:00 2001 From: Nishant Mishra Date: Tue, 28 Oct 2025 12:08:02 +0530 Subject: [PATCH 23/25] chore(docs): update readme with info about play store release --- .github/repo_photos/banner.png | Bin 166810 -> 0 bytes .github/repo_photos/googleplay.png | Bin 0 -> 20440 bytes README.md | 36 +++++++++++------------------ 3 files changed, 13 insertions(+), 23 deletions(-) delete mode 100644 .github/repo_photos/banner.png create mode 100644 .github/repo_photos/googleplay.png diff --git a/.github/repo_photos/banner.png b/.github/repo_photos/banner.png deleted file mode 100644 index 90951156f8fdce7eec888aee84bebc383389c800..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 166810 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

%m7Vh~9_*V4JOJ|LF5 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›`*I@|Al|hA`2s1q*d>ID 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%0D%eM7u3>kj z{vteTS~OMkYva^C=T-Nnx8#!Qs-q8=#9sE>DP0pjO-2;Cgf42nyy|ZTt9C4SyUU;i z2vC1o5`ySgufBuo_>6sbm93b@A^jQm02)e?3d8j<0*AOEEG7K!ZhtoHR3BOxU?eJv zC8uVcU8TdEK+GP0Z?^{glMkzam4q`uN~zk`7*_mOT4Rkysi=Pd2Co(2jnf%j^CY#N z{5+rKMa(cCFT1s->HQdH%3fSXt$+gHTkWG}rd>q~l5?VFFSWMKpKj-N-Qt$H^p^Q?pgeya+NbS*pr2I?$| z*h_jV-wRmQKSt-jF>pFFYw&gbYPkqsSp~2{*Yoq@<$~9@=l>)mlHgF+W&%VD+?fYa zBKHShy^}p^T^a@b06y0H+@B|4NdzhO7l!12hB{}qSC5ftXwy5H65r;>XI-moe`joJ zgJZlXrGF9oOKD=0>5osNHU>gI^&l{*6FN8UjDL(VzB?kA&8?e%-`nR>m>8hdJu<&} z-^k9>=%$_WO$8AYN_TkOy1>n>@Gpn&y1=oH5%_*Ws(F*91rl%Fj1S{j9~2Z@GuZ^M@kblTimIEzMtkgL}*?L`T=LiV7ck zKHr}YPW!sh{du7U39~eAwSB2#-WR(CTs2Op)*DJ(8@;7*#E*u`{tqXl3QKg6Nb=a&%13pwDDNCoQ`uA>YqMVhq5`wqmjCnh^iD%+UlKChUfe*CCW zRE-6c3jZBA+$AELsR^ODZ)#;G6Yw>) zl@3P{qt!1r28Ln~1$?D)cRHECnacSVV5OuA{npy>FI+Q~-TGO&aa>@;A9&GAk3R`S zSupYl+5fZ#M9|;m3F0xaC1%OwUWZQstR01K!^Wtg+%*s|Akc2 zdw*%fDh~9`phF9*eEVC-1rlGuk-nHFmHHf%vSFVrB0*PPqn0Da=jjM&r_gEB7t8r$6`Jhy*xEnU%Mr@(UJl=g~vmOTp{i&jjvE_#o$1 zYIKST$S3(067hbgKG|h9VPj}^$YB`serE_%U@GAC?MilzwlRBZQnL2je$#wI;2PgxdiR*B{`G{j>gc|qaY3;_hnw2s`9X4V!Q%p8QHpX_G<^Me7C>={A zmFF?c!uO;y(>UJ8wFGvGtU=A?liNIe%S!osV|Rg!kG)Jb&T)$G`uI zXz>+XoV-qSO4I@KJkFp?(BJ^hq+E9HDBIjK{9_LCwh(ETjDW<%6maXkXyh>2{mjC| zBDOi%W@GQB?YVEq7v1 zZSOxDKpyOn;r|?5+W?IqrWx>2ni@mp!$-pJc>K z1O9;WWk$Ju&c~0TsVnEu>W}BRo4>$a3=%184ntvcMZ#fn0hpQ z0jyGaQ|F6c-VSX|Da&iF1q2zxU`3IAiZ_x#bK#(?a*JlL$$7N!6vvo;Mw!yjrZc%o zV@<8+{=`3RN=jMio8J1j1VFfZD-az9)|78_T}&+N)`v`R+3Al|4!GV%ec`V+gi#FG zXXZAw-tau}`a6`q7F3y9_vbRT!96~uTk7h>Y&3sZRrK_zaQH~rRb-z%Bj)8-iL=R$ z#Etx!$UcgzdEqI(K~3*^Puj5>M5R%Yy1LpYvvm68{jt@$ikBD~-Lsljxuc*6cQp<< zspNMFy6pSgq*$*554E{>;M#E>Vbnu5XGuNcJZ8 zIT0ww1MX-lvi+44F%;N+RnByPNueLyF7RD*Z|tNj)8AsO%nqJf~pjyuM6%?!RNZh> zI&vui_2y{#7HFjlcOE^Kq27B&|LsYG+i%ckOa1d^Og(|SXpz9yhFTi`GjLOtpSF-8E+ho!1=e zO5%^NcCtbT1_LISz`H{@KQJ|>jJT3rLINu_4&KEUZOtDPraMbQu)&1a2r_jM0@1<> z;HAI{cd(3n37vW1`uRi9;p^<~t3wUqWWV2O(C9jo6D0&UHC4ivyQF@SM_UV^bDJL4 zAaY;7blaO=t;b^GWw8egad{LzE2M^S-$5$u_7%_+bA>7EKncM*V9&|~>i{M*f{@8Z-^%!Q|GH4M@%t)M}$g3z^xa$%5? zl|XNdHupzxQ+{M*Z@}Hxx8`1O`PWqrK*^6uX!%=~Pm)+av%OJ!%ni#S{8_a0>)7?1KA0+bY$@9vr+jCR696h z&CXZmpo@M8v}{ou&t{v@pzVvg!js&2uUDkRd6u|$n1=DM~W?TOG?0)`&~`;xL7ca^1Rh)h{DS2n}?2jo>roIDDLmsa(kHa zsLx0B9o;MI{9}7o0n>*T0So5mD`g8uHd3~sY`()MUQq&f4(;7=h`vttCZqov0Okdp z>et&T!D2nT@x#u}xtJYl&vBZZJYJA?wF%Z3AAN5-OH2+1ydP+*R4$3(Lvt4SPlDzX zz-hxB5vr>TfJoL_y>7c%3P%0HNMjRUt=t79rZrh+3;6v|Eq|~1WoXr$0+3>JP%DR+Ub=QaIRlW z3i=y7b$|_03#gx%m>3!u`0!Y^_g1E^@<;vg>RupDBpVjs-Pc|Qu&fH3Wq|fMq072vWFAxFvFK@^PGpDfEAYQkOOwGsnz)c&)Z!Tca?C7%~2a zBC$MK*}C$kALu`@R3j3gn>%MMd8mv&4m5k4OGxNReVt0}zKtUTL}K!Xs-ydL8@xQ6 zIP1z3pl6RZ8uLbwr2qw@9pgkI!cIn{7!l}DYjEKP6Pcuol2ns>@7i)R!YWd4xbf{_iPv^ z>j>lx^o`^eF!JOkvN3oLhdSci5`@in6}!(V6F?yp<^yjvV-%j=gm~{QRQlM1gdShr zXN@T=wNDQ zi!bSnt(oZ@dM5HZd9vL&ETWqiXrFsSBxa85`kEIRTUa58IQGGcEW9lLEk4astMOdq z;@@POp`RQ+j$giC?%yFf+HeM*zf3>>k2p}R7r!j>m;B+|+5fq6S-Iiq>E74@_pAY4 z;O%j3L5p5d`q?!$4xl5>x4=XfHjB{)c@vTF(#vy*8Hxy``RHumYdte$-`+gMK_Cma z>|@7!s3AP4IqciYWg7I7BOy*Et8wr;Yp3Yh!Om6Hh~w{SFFk7Xo*v$QRI6|}Z-P3B z#{_M<_0WE}OAD{=+CbeCm465PVD~a@1bXjQf?I|zV73IXqi_R(pk4pVdLlm9DtH_z zJc$sx;r#os`}V)txNj)stkn^S<1Br9^DUlqJhVJn62z{#@0Q-M{9V=9tM@?^`@UJT z0xXV?D`2&a62kv$aUVDyU*G+X0nlV)k#LDYuiWg_#^`x#QC{AEv3Ci?c(=m)0=LW} zkSbsf{n>|;DXpKX!7UtFWAymDI&djiV=VPprac_ z(oQUmo~PbjIfIRu4WDB3;!)vxGp(4Zh?`j%GrvjXa>@-=im1viL<~4M>T=)`vZ8HZ zd3(Ram#$NI7GOLCf@hnHpn0y&*|H8URlx#h$YgPZcO2w6Umr6J(4y3zH8DeLMOM;i!->qw?J(FQ-Kg3W=n^ZC9sbNsvXq~pU<%B$?gLuM9_0!Y1k0(MgybxPFr<)dK$1>o_?^cEfGj{Js;c%k;Ix? zuvLDtsvTyb#8Rs)V82}5F;<#GAQent-BCH|1~wav%3YoR++FBMpX~Vz7iuPa`}*VG zd7Yu3A3+RACde_6`PX_8%rk_Z9aSpOITMeu&vc<&r-#u$WL0r?F*nApJL#r;SnmMe z{cz6Wey2WSfT-gVgvZCO`w2WbiyU1?_ic$@WUMrGxojZqE!g1;w381-0t#P{;Wmfx zW7`QHX=yUTrrL=b!fOtB6eb~#pGjmeSRE(fW=e>o^unWfXh+`veJ+S2fzO5;{G{t# z!nR0_0n8ANZ=2tUk#UsrwCH$61zt|1TrIO?S(zwBW@4|dETURzRvmh8zfc1@eEDyx zmEY8lR{9Mpn@twi2Sd+KP7mMnw2DfX<3b1T|I`(n{_TVpb&bD0@9vBn8KBm&X83X@ zfPjrKRxU4&4Z6`_V)3NM6fBqgch%1V>m@k)ZfvwJE-nV9rOQ!_jHv1Ob<;{6_*onP zgz!Gl+40i=h6Frb>*Vsc1JkcjpbaxAw*1UL0Qbt3!h=~`nQvFC^03E+lqeGKq;vZ& z-h`KtC%aew$bgR!7@Cmre0va3-+X)fb&(F1dk{IJLsYVCHlLZrj7Fb;6N;e2c-G94hXFP19rfI) z1&JJV(|)4*FX|C{DD-1v^+J9AlfEnP^PA08RL*um3nJTnYd6WSxF`Um0GlBdJ+1;= zfbupe%InI@gYyFkLHa2|C*2r+_<_xA>!RI=bR2&o(c054&pq5fCO5F7Q^S3fQP)I+lf{<7#9I@ zsu?go%QGP=b4HmnF$2-y(d0Jwk;mf}IBtRRQ(Mx_dKO$mdxzH2H~PCB zAbFdc(MT2Gxz4Qubp#JFWcOrMR#q7C1N*BVHfiB0f!G=3 zTxoHa!jTtNL5p$l!D9ll1w?z{R1bCwPt8UT^5}qrnyF;hCzm}HB*bBLPrDyb=r(W_ zK3>t&6A?Cukn-^h7FlJc%jVpf$vx^uNjzy?tkCahiTiO~zLw3bl;P7zjyU2_kaYsL zbJD@6XiPwF{@`Z0Dh>Rm|1cDL&YXYwJZ={KUm3&q_pMu=mR?||oA2^py`h@TgXjgn zRAv5;b7!P7Y;@S>=;*b4s6ru1_2BUZK?7@!kBmbnI&GaD#=!)VK$ z4Xf?D!n9yC@(5lD-Mz65rSSwh5DW(uoTMu1gKQesvG2e`elH3FqM)=b-%np2YBw3# zhfXEHlf2z#bKK?ft{;eeepV?WU)f7MG~`*?F$m~FGAlvx=>rE$cBnV-E1B zTy6hV(N*Y_WW2CezBp21@bA<&$+}#78hIQAq7$lBO8dPP&qh`S6Op&T_rc+`cc!A2 zD0;RX^`fC9;!S>9IIz<%R{gB*pfM#jmVWfD&<~!ecSQNY8K-dc#YTHsQU8zHTRfW`=UMWNjb0h2+-<$fZBPi@mSI_!a{z~(w6Fi1+r zdFr>qg%DB+Ow|gJK>2=LWWPCkfCm;G-Q((Ryd)k|xD!D%?6VQwRcv_&4AWA9WjFAo zEu3K|K=dsBPdccfh)KQoE`HPtl&)IXB_1X6_t%;W=x~hTft9n9E1U|N#}QWoul*_O zc9-XLu5P+TsVI=Bq2DxW{rL%@IIlw|nEQJAJ~ zlbMe-us`}VTcyt!L6jSbY|KR2C~iUU+$&fk|805hG~$W+3KKxjHKwm>(O3q`heBm4 zE-2qZ>N}xlLP@s-*1ZJ^Gm9pp-= z;Kw{#C`!3;_C~V2jnp=XC;_zBG5t)6VI=9mS1HCdB{C-cTLcIfg1$YzLN2pq^zP22 zC>fNRy_~mWbR*y*91i`quc{)$QL=rPqu509;BC$vX>yruGo6({F{W$ONmBbR10=c8 zuskbnB<7_?_*AKk`6bXD*e?=)r#N;jU(Hzrqn0ZKjjf(UWexi9kG;Dbm#5kEsM;lX z@6{A+Qd-Lr?lrNv;&h;3kOB_XQgRQHmpp!9(^fiIHo@HPtCuA$OvKvGR?2Ij{~<@K z21XT#)P>%Jmaly*GQSP# z7(VP@!8U-l#rKx18F52w-(wG!bJWV&ZjU$8jNR%ipEr6m5)C|TzoI}Qnc-f(bLX4| zA8w1MHHZRWlbeb5x54}*^liD0_=ZY7nKdxV8luZ=ca>cHNdVX-!sltF_M_Z1AVKXRb8GrOuRkdTzn<(m)>04D&N@9v$DG z7qV9(6oFpN%wsVD{wPNjf?JJbWC7p_hSKdl$^R-rBD>f zJ+0Ctivrmb(nmfDV4TTVUVNpSk;~5!GTf(e>YNAbWaptlvu9XLg1J>r0|AAlp6A{o ziY{FN3>|AQ{rcU~f)%5-tq2Mvz}+ccor>7;-dgaeqy!iO;o1 zm<+Gk8C=77+U1kp&#DNZw)4IK{j8J>)ekQL_6@8XdP+46Z|aAAx-3s7b+N|2L->~<6o+-+e4lN`Hb zjNaX8&M=%=6z9dGHz}_Va1js?$;(D!8M9;|SU+oPlAjlw!|wA}^*Lin zZ*%e#6Ht_jy=Yh#BSGQB1V)Uw=e26YSfhisuKwB*wqZHqF2BNE0UddO*E&00;<^80PgjhX_1mgO z)b*2=?gcvfvqfrz-7k2Yfd{+_qOMz+VuC>ND$#NBA>!o>^9^P7<5N3C8Z#CaYo@ub=X74R;tLM#l2 z;Nd>{o*+Qe&myts&*c2W+~>iib;W(<%n=UnO;hEQ!p*P*8%mbK|3#2p5zJ@6*C?38 zqBtYOdQa*$Z;EW_rHcUe)f?_%HpX(W+bY>bAxlpp?1zWRfN|W_EXq-hIMo56aUfUf z`qVN?N=QqgNXDqb5dpT(flIDO?=V}rIi!USYZI8wZVUtw>i^|%%?Eq#lJ)d}6!IxM zPUtj6gJyF(HTy&^#UBTK;-^K2YU=l1@L`O@Vck6kTzd^qy1mQ@SiXT)u0rt>Zq*|F z0KXuPFEE!Yz)W;7;#1-R560vPyddDE2hyIQM+cfYjSe5NGuKZKy=TAW4Ln+6ZUtLc z&QsQ!D_>k?TfEHhRLOGBAG4uP`fp3&qK6P7%?!UcSU`cN3OE}~( zx%*jEL@^Lj>aAZqE<7X}N<`8?QBhG*Q zR!fwMH6F#>{?vQIMfU%4aHnst!ph-M|`d%a|NVQ;oJFx*AM7*zpGydkFjO< ziuoC?RciE~3<`mKmp?}S4JZ*tuY0@V)#8|fReOf71YToOdtB7qo z$}UQ|l?J;V3}@kpk-bZi)zj}TkpsL|`+he*dHtT0*yS9sI#%lAjDp1-kt9p29^eU- zGV;dU0?avlfl~?m5HPGs;7K$~f!*d;oYkXa{GRap%T_@nMuD;F5+flcWgHhz9%gc> zQ^&KI=BtxA-EGi13shb7%775&-*TLk@h|?e&20WD9A00yKS+;{GJ-N6Vv z&9b-&XV%}+bhy5CYjk`6b3Qb-xf4d{?aeQ{#ZSldJ>lTThXT|heTBuMI9c;X>C#6q z-E~wquC2-d|Lw!cM^|3nJRe1*XE!q>hDx4K|K;FhJknMA^>y+elckMyilG!9pJ_E! z`SE&>3KoH`<_%5@XseXwJ)CL%Pxb9XBnTHT)maW^F2~+QWN?5y-m!ebBD&!yH&RI9 zy&a@r?2RdA+HRY7+;#%@17eAiCO24}yQo0`IGdf^RD6f9IR}NJwrcW->#-9zd%&v8 zE+OIaW%cEwC1f1@onm%09!b@?=r6 zX5B1frpKoV1&D@k`v`lG+`Q<1Y(1Rr0nlZ=&7a61^P8v-d9=EKH;ukq{#3rgu&qFG zO}i~dI@t~irq0)EqX;gJd=Ui`xdMvtC zic5#(58rZc9+9A+y&88fm_n74Y3cynw%IDph)JCYmgIqx-4NP{d*90u`g?7@Vr0!k zt6MwQPx{b>_VsJ<`G2pkh)773-b@AY>dloWbA$_Zb&^LJ<$~S&G2&Ij%54{A5(tR4 zzrRv8@*29vf7o{iOuE8x-F+}Ty%`>v`>3j7<5PHH+@gQ_*K?D)5lfe_T zEo`e033!a7GX;IQEaXE^)N+Oio_5PSIZ8uywXv^&X%CG3=JcR^G<)EdVG~i=I z#k38*N$Kxz79-!7OM&U51pL)Yqu00VE*oEe%+Lx!(CHqz1Nl))vLh!GKz5$J!OVt6 zV*Oy07~z?24{}Sg=eOjq zQnWi;oI~~`t<0~sk8m5nr?WYj4->xAmIUiJzRZ=bOz25I6%;* zob>`ZCFB=s2b^bUSxKkHWVbNi{$4Ezh3t$b#BOpR_d>Gjul9kgl!Z*&Rq zIe~-8M6?wY8hc@?$Z${l-c>wj%j}RvTjw+rHOH?SX(l<_G(W>TWtDMjU@Adb_vyU6 zMwZ!3lYVe}I0N%ghKq{~?*q8LD^n zg2%M_oGY@c+hOk+LptzRm*B$I;UQ^d$*JE|@Cgn}d-{(k->K+JpxPbCZ(*LjNGf9Z zr_)rNEE8g&br|v+%oy@({wl`&@+mkI9R0?f2W|T@?`~$IzwIk%L_4Rovi@*b!(x&_ z&Y@-SsK+c@=lELG#a+Cb3IlSq45Cv6(GK3;HZj_0A?B*#aMLlcala1Df7h*^ke-Rm z?4Z3kJqSp(OT3GLh_mXs+8d7mHM~&2cewQy4vpctQKS0^ED}m+fTY9 zm9HOcejM_f9~3LJWFQt*$|8*!%&Wg@dia|U4g<(|TPv;~xbk#9m_oCj;o;j4~iaj7TPa(W-=>dsM zZgqfCZYfUoe91ZXewSyOQqXIHb060tN(S<|3PR^0lZwA7znA=SPMcEkYSvYVu4tV( z5#To9tm#>B5pZz`d6PMG1B=v8QDp#~Zu<)M&nJVcBfAOPe1q4w|EbYT&KH6)u+B+K zQ$=y;MzaCUEMP|T7}%YhTi? z*_SlzVd3J~yi-+=^VU<$VM~^QrLIY9|34Ja4axvdDnm2OMY-`G9byahTDv%!t!C^_b+^~+`|O{<1wE*d*K&?U{3@4LJ&p? z{eBK`Kq$h*#O1d?eZkS399Mn#Q^chvE#o>g$d4!?l66l627JyJbyu4{{9(WRBT=I0=q+oQ+ko znfjzHxzM#56_?2Hzl*!J;0{lnyyB-9`DMX(i-#$?>z6;pdES4SCRGMKy7ek~-KgW^ z*W)(VfnWq@BsDOLV66GfS*hqCYQ*KaH~7yH{|mK>8zD--f!fX@fupWoATHEj@* z0LTZR7fT*C3MjJ(_UxR#-38E`1RDG7IA|MvG-F&)H!JCbM|c!_<9=M&%vJ>dU(1{JE~Sa^BpqcS>6yh6aXx_8IoVOgHaeL<4V;S5 z|7d&|TJMhwoeGYOeG1zVG2VKo$kRe}6br)CVMT0c0mTg~x>3y!9_^?&_2>V^1)Dco zMYoTa)aE1C%L-4f^gmWO&8z4}Ul^&Yr{da|eP)|W88aDLF`5wr-sCMno#9esP;dfi z%;hJ$OV^^Ddy{{u1_lX(my+xQ&UB+ZH-#loWq_bVj1r(4$dxD2n9g4Qt8#Dbz_%dM z>B(;VxvoNgwL`Q_1x6KHn|$Jn$fq)ISSW_GedrjOIVAP3O=~$gelawXVC>n3ClB~w z2iivEw!XvYBc9s&E1gOqLPn40jG1;rSp;OBkhO+{BhQ_iZGyemzr@n{cUC%U6c~Pw zmH3Gb2FB{!k8^ONka+uMQi}8ZV;w0k#i9Y6BsKKwlN#sWsD0v?j6bJAJwI!;q~m~) zaZ-m8-XD6AoR3k9=_+!wV^tDSSz`W3MbTK&jz0KhI7#=|5%_1jv zIp{m&NA0>XCQbb&Ulwv+YBlzqL>N_VU@E?tki76REV_4H6PVyLsH~A@($kkQE)N{g z=ji~$*^#z_0>i+i8{t{XC#mTFGTCljxHyA*88j?l!;o*+r2t06-QFc-U;rqu32GTv z`utq3XEE*ELOZi6QM@HLG{SyVllU9oopeS1IgmIA;T5kDExm->M#s`G`op2Tt;6+q zG0J58n?~wMziOc?1H%)i-YDci&Ris`z_=TcvDIFgBafdL^cU-z%{A!k@}qa3&$H(R z7)#u_lH-%rCDLda+E=Sop7WIq|AV9X8~gINR-?eXvf|nTx9H!&(cg_YvgM4V8Ncg% zDD(c$lS9Vrj8p5`5rx|RIAwj?w3PRvtqlG4nV^Gp9e%&I|ZXnrKzps5ZwPrt>5r zq?azWGM5wCA?{kDAmz6r_K?Ti*jrg2k5T8zO&DZ)uZ0tdq}>JDRrY^qmhNUFRgZ-c zEw~WtYGfG2Xr5NdkIal4TmdKYgt&pc{+o<0!K-&9n4f$}%c8-<0a&VoiUX6+&wT#l zb_p`P3_jTn1_{N3ioZVS+jm7!Q}5q4ao{P(WV1A>u5C0_enqmp`NA%9x5xz1P1paVk81OPC(;fxjeBePnr@4F6!+>sJ#`A*RICD5&{sMN}jM@hyQk_3z%(dQ+K% z&>2Tzo3DE3YW#dxzn$9B28+SbJ2c^HLQ4L(G_F-nS-pj&$x@!Uu`&_cB4_2bJmVQ;+LigzME{RPEW1$Q~Jk+ipmG4jo0q zh_IVvAfUicxj*S5yXrA)y(ik*jO?T8PB9K>J7x0jT+k$QnJQA`xOP`CRJpV$_@D0O z!#WMWCZ;Q{4~$xqM!P{99$gY!s5FTVG`eedbvOD`i-N;VJxYtdqT5ENmFPmuN-nPj zx>-yuEoS^1#PiMH(@CX-pT2PRUOusaKF6h z{B}8s!mZB6MzWBcfc}H5qL7gBX-%KW_7^RGdk7CC1jg0fB`zlmc>D^dJYtb43?#Q& z-#3^gjh?863V$)`yyn2wYRju<)`|ufz5L|+N>C7tGKbvycieh{APZlsP!5iftJrAD zPIA7=oL5zIIgAp-rtk+)*wn9=!aPx!2zA3)*0*0N@E-_+g8DV+^6g54t}p&_HufAL z7o(mUXZd;&Np!l(7hSuqnsnzqd#K13@NKdDObWL?25*znG6zex5`S2BLkyK2V{+^e zH*UsNR0v^qK>b53wc4(1xx8n`_x>98G~*yBRDq0wqd?(6)Y$4U_Eklk{LK&?N1lX& zF$Z1px_MvCpm`=fn+`q7<;|M8u9rgxr>;pU(i&l%Zn?xfgVz`8O2B{XaxUPJ_R6*w~6;d5NN(e84kU%?KI^5Z~ZQ`dOBs zV|-eL`n7{J8wu>9mY6wEi>^B$$yVK+PPzOhdng`{QS^yZ+o`X+D29AexS3_`hmE{< z3X@xd>AD+Y?gB2^ZhucawefmY4AX|cMgCy0;73P>+c#~;2LByNp9sB|y+a5*`=*-* zFg>7?Ij}*D#Ai`s$d8?dlLe}~p6{|IdoL(Yl`nQxeqMZuzVI!@c_tv0w*V%){0CBe zd)_3?4X1ywjU`yWOUxy=&Rzd$Dmh~h2T+~8qO^v}_Lr{zi(4}C`ZHY-cE_1_vv|2> z{`$e2C5gq93@Qvz=H*J%rj>-l8`bIK#Q2wKol3Y}R~2>lMlq@mB`EU+!<;VBV@zRk zo8dSPLu2K7isA6qO#Q?U;RkjLCMNm6EYbRZ4r|JHc=e#PIeTMao2+&@WNy4yFq_wA zH5mcslu>-2*ZB0n*QMb^?Kz5gPo~Vt9E>jkLrehJ!Hhh|erH=Rgd5l~|_f1MG&Y}G)KM2nND0I;&QB$jxx8U?xUk*%#>?lY4+_#ES+RF*WQ|a>a-t0_q?Hde0yv<$hqHVHH_@}nc z`K@coGhh=RP8k5=3G;t>IR-@APz`R9y_z{j@?Hu&Ks{`C6m^xe3epsAI|Ls%kTE@wgfTD9qXwrRm)ST3#H?BlR!EhqO7a{Bp(rNfyBtYH=6C~~ef%*)XI`NoY& zSj9n4~X{cB4-d%$ek@9|J172OUC*F@cDWFoV0RSRF96hAa`}p#okAUxkFn+ zq2Ex4ug)Vxa{)L)B#9XlLJ@JmOq1@Fumh={6^ptR8?leq5W(#*Y}6)thc@Qw$6q`d zIRhv}Nx=q2bENDK86lo<-K-h;(H}#m{pOA9_t2*_#YK+1U~48SVk?8UsH1~dRg%&l zk>hQ}jm^zV{HHhhkB*tQ>*hC{^T+Nx)8RA@)>>`M1k_;mgYgMH+j&YlK5^?9%nvIX z|M9Q+&U?92F9g^BA-8I@$@CVF%a2lo;Z{vBKdc^vczx3g>cBc?5~7b>jn`{yrbtSX z*aO+)!a?W-wkB&JPkWFvgy_7Qv-kV%*F!~rO+lb1q?#2Qjm5Nx8N&@`1+{6c-#EQ% zy8r&eV(C9h_c^Yep+ZC_sBwxjrmNzJuDsI!l%Q~|N6*zJ2xP)$S+q$7XfKiI`eS|a zrUic=f-pkI8nipssyC)7e<0cFL*&Dn1lkBOfU$%q(C`Tv58A2S+fCRgrg*x>9%c}} z%ARxu`9f9xAVoDD8KGH|!s`&?qkHEfV*%JP^Gmy3T|20(*S_fCT;xWxa5J`k<=%K& ztxLn2ezp#_{8bir7%mNQP1Y^i`i&1csT=yky6f}8!|(E7c$>I?ze*=ZfQjDTAk8INPdx@R~eN%T)vI^D-T-ear(ub2*StGPk>rslb! zac)+=xQsrK2Y(0I*Wlgqein1{2mQYG|8Vss@KCl<`=d?0L`76YX_1IhkzLVlsbtF< zp|WP*N2?GjA%r)D5EHVDZInGBiLsA0F&NvJVYdHyhTiY{{*U?jwfuOV=f2N<&ULPH zo%_B)?#+iYCyrcFbKPBae{QSX`-oF!sY=ZT4W0L7&0^!=Cl(&w){lj&LmbV=@UHoeOnHHOlJL9^TwwWkh z8p)n#5><9zZ&*x!I#)AQsi|Y4PPDB%OZrvO(Dn^$KOD`876^B~+DaAh5cPd@gGDdv z=<^FMLDSrxJXEHuUpVABaPe@w>SfTet~#Hb;d)PDCsSTFQS`5jPf{$7??|J8e}Bad zud2~6+?VoTLS=S8<1Te>&NeZIZoMN7ARQE&9MHqU6py zSFnrLh$7I1`!4F< zAZI1~VtjYx<}}%#%gQ*MSe|w1pu>Umr)Fa?b{po7qpSL9nLrNQSeiV3V>V3aRUmcO zhPKFOdA8BQvnQjQUZQa@%Y?hHvOV;umwk&T+SZWkryFpXI{C)@YP z2qA(-6{LW6IQf3o`F1k2N3BQq&Z+QB#I{gj9Fhf`Z(k{Ud)gyRAdAr?|9N?7?DKL` zPdj-;o10VR<*7d=hvTqOmu?)aKO%8+5B$LT>d>0&3IR_Jd%e!-kk@JbmY(z@lZd%C z9iF~ZM`TCHhE!GbgG-*T-ww6DvpH+Mo>l&Q`CVkY{kqCOsYNZ!v}tye%7!QXIBYJ0mM@@kaA&O z4#Tfkv+;V(dF_F9fW~kCi+lCr_O6ebZI@R+6y3W`+W5ni=K1e- zTt@H4K6tmZWOx%L5HM_TVj>HNzN?uZit~@_FlFis@TtTs&8yrEV0dhg+)bN3xxTS5 zy5ZIi9o_zyjwTKFhNFe$&CP;EayrJ6+Dnw2uKtee*`ZS(S7m!h(Jex(=^el0u9OQJ zRdsJwmX|#4#)qDiJKWLvA#{DIB%{CUuHWeP0><<)k3P!U4UbsLhTqN|E*!aXAWciJ z%;&uW1daDNi##df@Jwt%+u9&RT&B*NQfse+w!GScWCF;S^-7f$6v^Wy z2GarF{c3GM?k*U7EY!*ER&1Zl%PP@T(XeMR<+B5(cV?H;48Jjl?``0hebE&xSuk&! zT3d8T;noMOx|>L-RJ8%u2x`@a;@NMzJs$yOr)|%qKj`R1rXh(FA7Eb(RK>#NMQ93&EvnQ-)oe-4w(=*gfK;dqJ|?n z&^+6#F9lhxZ-VlR`V3#hTyzcQF??TP?xfwc+;=7Eb30FxV?c ztp`9@aVcCl^)zidy_tf;bfB3U*)ruHJb3%EzFSNW=g%5&MZY-{An$CU3kL^*z$rW~;pMEWXeHdJyogJm8f1oJkn(h9tF7%SLj91s93JpLqG{>W$HEz@R zYc>-7Vfe9KyAPph&Hz{Yd`<1$I80}R+jb!(^W2+N9d*m z$=HSu!-=V)=hrymD)f-{x}&PY&5D|5mAXSDE5Iaj=0M3?6j###WG zO+nW7{eZF;yLt5;vKm66wA=ab>CpC$d&h;n=wzu|60Nu{#yD| z{*6K7<*s!eOY0$}cgiUp>Q=ti`bA?TCOTh9o`10k!Fk+O&mHsS_p?DTYWvXoWq(3y z#yoH2?V7Enuy!ZG_*T9s2cdvkGTUUg$y`2QJ~*OespxRLY!yCv46I3&v9zz;3ftZ9 zuQ$b_2Y0jP%DPE3>@Vz_LH>>Qo$fVuq_pZkxuLu}GpYZcQ)t-#5PnEKQkCSDZJN=% zy|EqZ5cks=m(dJkw7`YF_B)!Bi^b7-*0r!-|3&LC|D9bQFK8!<>FbAHH;_2; zeZe|PZ1clguzH{0iC;;jp4^;CO1g4qh*4*DW92( z9%pErMYY;JVI+b%<~pIX#y5pZ@l&PN?v zlzj6PR9|{bW+i$K%cU6So(>25kho@08+#3g?#Ec(_~#P*$E%d?lN09Uz6>>tdFuDf z=x-nC>TwjqL-}+wo7nQyUR=^dl=ZId*0UI~(3IannBwtgt2hKIhFY6ATu!<$ulAiAM*JZ$4=Y zOBRR1D$#2uJ0n`p_()NTsneafkJm5t74AE}?dFv~Rrtw&JjzS8%)smy2p0OwA;F_Z z{O%8q#DSPxEGkVx)}gp}c?0(3N!Lq_)Bweqki|6~&4zFicE6 zNl*i6r#JMVR^tL(O(VxX`3taQSM_##!$8$DNF2*t{G;d3G6rFrrJM6Vodvc{XipxK zO`Nk?Thit{JVQnF0@&mB~I{XXXt-Uxn>|$>kk3t%JZ?c*lDLx z*_}RdPNR7W60r9~BW&~CFuz|zmRnDD^Tj9JjW6$*$ZB1F;s`>yooNkH_t(5^xCPBm z&3iT&DT~B9_I&$XAW=TI)}x$N@l(>^1F_s@!q+b2CySm?lFSGPnH8vR!t-pqH0r)( z=0xio>@6+U^t_YtF$HFV*O~i;);FE~x5UG4iEqnGX$>bi^>w5(VAuy8PIw_q7EPw*Fl}NV_XqjON0W{M4ZBb3OvCy*S>T$LHTufXC7Zu9DDr_t z-92jHCg6EqgHi^ymBaZ0Ae$ozDn?i>c}VM@AqrKlJ9rCo`7gcXSPyoxPt3d@j^13? z{z$wZ+CH?Q!ho8Q=!)P;HO#(7$<)7uG0Mr=PLe2h&nW5l)i7&ON$pi?33fWTXuvfZ zA)Ezkrgvf&7Fn>@zez|$n_LrXEA$zHVTPkKe-Ms958!qSK@p?0JBMFfaG-l>CZ%hg z50=f&{`R>@qOCjA0r~?Sv%eJ<9`5N+gTJ^sI)3x`EQ#+=Gd&;dx_fHw=N+GM9*MCA z;`B?^owf04+;wKGmY4%od3cs{Ps~lFm&5+_mM7MYF8gGK&({VkP40@=S9R}J$=01Y zl5HMpOk5K$i$rGez1X=lqIUikHs||={WACqC8ee9t*u|8xORQ8PmOEO0@o5POTuBM zkwrDR+a{(WV_Hq^2&r69L!J-#hrIL8V)WE5cVpM{b6 zGyAu_KwL)HeH3Uc{X-!u5dvAw;gUA70yTH2kcHS?ANZo7JpZUGSW5T@jT%SGuP`+)rti6F` z{@v)3SX}ydzs6T)%TMxH-epHcZ+*VB_%z!_p67+x)dQtvXFQFuK$t-@lR^f3N0zd+gEHFX+37J0KiqRysnnENBALr;v2v2xMd`y~c<;c0$# z1pdagczS;1rI_F?WSVl!-c5EF5LuLo_HPw9)2>m{;iAbSqvq&5c!c+7I(}r|I>{Yl zY`!<^;~9gC86U6TWw88<9~MQM;@sr#%Y0f&Zi71zOJunp3VmCPLfVZ`>u01Bi5S*z z(j&~gF0OU1%JU%eK<8FA6$R|0kMlNgs^7FV*DRPWKT~sGkV(GoN}LK{EWyd)>Z;hB zxT!x^awM}&4P*1hbI7bWI+FOlY*VkIvK(p9$Bfv>&gI4Nvb+q;rNv3_WITVn64g3) zrY*DzT5IV&xsyXktj)9OEYzxFy4dY9Ov?|9-6gqgsm1BURzrjRhub`ip_&9Y8gTdU z$jHx+I?a8w?jC;_^gOpX4&c18Z(I}M=^qDrYrBJY#u-d_c)?BpFY)c=OvO8Lk}^>* zRLcx9O&5pN&i4o7!sIqzWCdg|s41Z_gjw3VzA~15FsUBxIU~3G{1ByE-F(NB*?SB2 z@dpWeIoJ+zhBeve_se0)48Np1RZd*|)i(ZUf1=Q4>~pS*;$M!Q-gNI*{mGPd8qarZ z*|KiUQ}r#H;xB7l$PZ*W+}G6@f8cV_G&;T8`QPDst78K}L4sxfs(WqIS`(b(H)ZC> z{1cd@9I*VRSs@@PGhG^kzhOtd_)~%Q%bApEXV@M{a*i0V!fNA|{Kkmpux?yyZP6?v{qM@KI+q;6zEB6>4V4xm-OBEgHa9DXGSKhlcS=d z>XO!IIZ;ZB8g9KL`#K&&b^4S;_`dp{X!{=3`{e636zt8o(1zPHWHGB%jf3yb)wo#P zl6CwRN#=Hzugdr4THHm~mV}DV5GbI)<>I0h)7V^{d8Xae_qxgsZmD%BC7N62q0ndN z-n~gmvOT&3D#1s=!d%~r@+6mE?R`Za`Jy}%@0TyailG`R^UY$YUOnhzEeTcO=qdbD zc&SBVL^W>I%xi34;1H9)s?|KX2;etdBO3@;zuV^j@^C!nO5XbeYOz;e54sz75Ixe` zGKzNvC0>nz!r&#+U?<)~3{}0(5>?-dK3X;#^`zBIVQEAjG`vX-Jassl!o|-`U$nKi zv(C}&amYAE3{L9P6ZY%+Fvc8CFjbVCDXE~8h3mOwap4EMZc{Ce<}W(M(-fM(njlG* z&o3g`)z>#326TZIfDb_-EqSh0Ayx^lc)KzM?1+4dp~x$T+?29R%dyu(1mUZ6p;=5N z2qc-?LqzoHJtD1vef8FkY6JQ**s*Yn&$Di1?PSdATmHkz?P4zw_V{e^Eq(n|smoj( zl^tZ?a_-=&l>vQ!=$|n&l<72W_hl4H;Wh8L{BC~tWVFQwQATbYt6DAG^8C{RNiY(a zzZOFnU&<-;@5$=iU%ve#C?~O(`@LAxc-xsWLF^}xv%z)B$i_HLs_}%j^|2hIwi6jd zMg39PY11K!OP>>dc5|gc;BWr3FTPm1FlnZ(|9;44^^UvenPZ&2qn7KI8JxS+J@W0_ zWXxHvi!@^TZVS`cFq|5VBF*e`{;ZAfM3q^LKHiEd-mOcW#1y|m8PSE_{%EbmO$|=r zJB|s@V#s~>srY$hDpZ+nA?d7EjC%@X32=?<5VO2L;$)OQ%ev$>+ z6qoV8GfitvzAWd>Q=UEV&VH<*I(YlzB9TX`BX)$JlW6>TX2dmJQuiPq7l*pEZDI;X#Huw?{&nLZn~I8bbcRltHvYc4~8CZIvBPCUj`)piArc`}rBPxWI-*eSN&g zL`kzNRv9N$BX|DCT2w6UoUM?TdkHbWLW<-^96L{!3{@Y%)$^E{e9k6@Q7b1(1W*=vDTlO5HVp8z#J&tfKTkPy zO<&(hu7F~DpG1!GZ>V*yN6+>y<~DOECcba;LGLk*8TC;!G=2KW`9$=NflFvPvr^Bg ztE3?sBk)_E|1VxiR3-nw{yVW@$}{&`F3u-;g`gvqLrW&0bR)?OXB&EfMNxs-*j7$A z>3g&2>Av~zWpoRst72c$I1*)1sLHFaTgHr~V+E`@-Cw@x_lPCEu=;rtWr&V~{orJG za5oSC$bU_dno*$zy!=co$S7Bs6bc>r8h*CfYB1lr3M=%W~->e!Ox8jq1%#)i`z{O(5v==3qN1li;Jw=lxGm@wy{ z3&LI^7B;zJKW`B_RqI!t^caQ8YZ99J<&g;687}!J!5yGE6h80=xM4|7zBxuaeuL{c zUyxhWRSJ7`;`=tD1}>zd@FaS4**srza-n$$y2fcMtAB~*mmZngF>fnV*!4e)&4g;G zs4p)=v%|e&a;lji#bCIE6H9WAC+Zy0^t9`&x_!b`#Z#J9TJkq~1tlu6i0+CRnG;)C z%Cz;*dlFIp`-o&kI9_3R_SF1R?{x?PPJvIc7u%1k?ia@}KtSK=XpR08sIv{CS-&Q% zopWHZV5>9789Yv6bFc6LzhRdF_PvA5uJb?sw5QY~+_3G0fLN?(2iO=F2WoO;iQrof ztM$88?x|z}|w;F0o;q^{u$wr>a$UgRH` zb~Aq!MWAI25jH-Sc3U^VROzTw!(X8jmkvWL7wO->pc42If|D;2`If77dk|?8a(!yl zI@c6oHXQxYK$38LbS@pm8?1r6cy`*Iyc^l@w$175bVZZ+P4OP_X}K3H*UThlWFFSn zkNbxkrO+!;*~ps7_ZdqM7|}@93`6hZ?>7CEUph;=k2w4{Dq-ksXC67Wk6k1lNWSc@ z=+nTz1Ru%1RX54;O(`LaQ&ZrfSM zk=$t)#O+b#!R>iyfdBKRpqm|MIm<5o>GG!gNlr5plb^R4mVFCRV$ZpHzbH!Z?9IJ- zCb{R#@B&tAOZuF?<$c})ei{&@hnbyh+#B6ZstH>@jz8?{zpUAc5(+F)YR^>K zp?{*Tq4v<^LmX!F)n0g&kGH3h&pw40XN77)B()%xwnY|@%eum*%;$Wn!&v>gzZXVv zeG97#jSKMGfIDaSxqZ148>C_zzmK_rxjjEm5dI+5IFDYVFukc#9%8QOu^avcH?R*; zs9S_I6z*_UY5c%-gKOd3&We8|4fpKE&_r0OvnO%rzq4DZIswq_Cg%}>u+NV6 zd!=C<`97miz3OIoV<`c^20k-iIFBbZ!Qv_86+<;QSq*>-ZMgLYoLxyydC2-8(`L;) zZNH&p>XVU|=}95rN4K-40Z?vJ>80X{HxaBw^N1WKfH8N(R*?5J7p&rMldJsWrgH_V zBiGh&=hoPA2W!+Rqtr!ciXXt2j=TG+{&B;aDypsLmTRXO}Q zoA-#H%u+o!Ym6Yy45u2>ONUQ85Pk9md-(r@u3jZg;sNw@+l4$skzWe(E0ZZbOWUj$ zB)dG|c5mNNjSI;;l%dWz%VwUS%fPK3MZcXs%_w#Vm8_2p-0W?qM`k>8Cq z(I^)`y#_f(z8m?nS~90OtLLRs*}d~ZUvzk+n0+mE-6H*9%YWf>2jzm3*foAE={!?g z2T~Budr8pk1J|cbV5qWjMo)MDB2m_N3w;9I6sM&ri9%uXg|ZfW%U{{VQ-i&EtkNB|YFroYP5=@wJGH@kdT^75_PftI zN60a?=SJ{>%eDU#$OF7Qzo?el72F89F8}YLP#AN>oRoy(KN(5MCh8#Xo~Uy&5L~C) zfZ5v2%(=bmP?KNz2UrVSyxJU2@rk^iVxJnNHz*m>jC!hiFxd!tAeOF$P#sRi2ln-2 zHPb)N{X|pecPf+4{&m*=aMFlu{!;Im$$!l;v0p4L_qr|-=9|Xm!HtG-pg!Gq>&!cJ z&7<_9smXeU!cCQt9{8Y@ND2qfkbS3e3?bc!Uqh$UT$eeS(4C9CE0yx^!4Ri$4iUOF zV%Uh4agA-$Wh}Jxc+>5dS0c8{p>LUa86K8FtNyNBlM~4;`KHnkpXYu547&XB%h+rr1!n>a zfcLWGD$$S5%j|u+-t`e*kaJoNalWB)8n}k8yZ>HMoifG}wb9BDfBJv@T7;_dY7P*J zrUc@g?)ev9{FA`YAT8vo4$l+vW~unqTMqnqWpih1UMXIql<9MPnNeXain6?H;E}jg z6?NY(-*}>=@X+&p$teFS&cyd0Gq3X!j#bvgqpJA_!j09a30M|D5wddy{&U6aj-t{? zeY)g9eq>+?<%G0^r^46ie&U(DzIV-;)+~k5aXu{;NQvMo){bh}uia+!bn^F);I=kB zg09W+`(y_>B^J*XRFDJtoF?Q@1X8I87xJ=hQCt^^#OWQMZe;iFSc3+Tc-Dl<Kv$4G>JO+i4M%uS^% z8xiV=U^=sab(rlx0O~YlMWV|^ep?O`o}zbGbq!LzxOyfDwBEAGWID~gL}e8W!zKb1 zoI4}y#M&mO3!25n#UahHI$0*{X;rnZe2>x8{VeP0qP0+0rK#)(7%R0C@O zG*}+D7BU2-E}f!S@xbvO1n|PdN-|ZtFQ$MEpF~WXQGyxUN(m$vIsDHH*Kakwt?RjX zV{FOaX|J67@1jb~BnK1?D*WdDmSd`T)nkKp>CelgQE$ug z!^df*3s?n{X$;8exn68u*O6~*08|5DU%vo?<=LCRY@ysg%k^d*Y7fq#9g@Jg3l# z*CO9-IqEaq?yN0=)s`;*c_Z$5pt6X`)7^&p`cJCflJev% zRg>+orZ-^UX_eL~&$cN~J^kpKJqJ-yJy`Y6IYc18v<^l+6HVgjJrO>B40Q|dbR#!B zSv!%rM|U~X`Q%0SSdlD%36hZAgu?1Br5Y7c*8U%uV z819WPxML^ulSI+umoDN&bqZ#+AI|Uku5G#n6{S?MuNz2-NW`xiWa)PoZeO?7<-|Er z)}5X7MZBigYY3Epe87{e*qXjF*czmDeq5Y?(nN@T7$#MD+*++BvLBc?*z+(o-c}Y?RcJzP4p-9+F;Q zO7EjOmpNmF)ZPXza?L$z@d@*WL>{3oN$F`TWDH_zj;bAYfvw5iH&zp=ErLxZk5qn~ z&;~Z|as8++$28ej;-A>QwW!Giu-PsL+r39QUQd&Ug@RW|_|?7-41eF27nUAXyBP20NKw=!*v_lN_+ko&d#vtqa*!;7)VX$B+fv}GTS)Uz=;Yuj%Gv4VU8|sAa z_Xc~_v!C+A?*vTkRW$(cag-e>2r9USv&1JN3PA}^9forQe~6dw)us1gRO;QV*j5!Z z=}rGr8pXJR_lRjseOzyQurAu>&R%fa$y;aqRg1PvCN>w?<6ot4?r`u>Oa#!$e|Atq z5apV#*HSp^_C64g`F&qE@M1?>E|sF5PBvqD{(qRSX|NU$P+;=qSMN#z_05sm{JQgb zCX@lnz-4J66?<9mJL$!s%WJ11`@PD*T^9dKAf*#XCL68R9L0V!vIn0ED_b!!Nq3`p zw!xkFT6arSUKn3XW;!9E6i3ZoAs`QiOfOiM&!DuoAt)1B!bQtQ$>dQBT=akNCrBtO z^YGchpThx=CHy=Q{Jk?C_D2wPhc3kz@qViO|!MQcd_W}=JbbZFLaDWzGGKV zW~FL;ldW;Kfq<2+dubmCTM6jVIh@`bt%FEfx)$<3AGdda0hQx61~pWygQk2~yVvy( zY}~L%e!0@sMDIroYnJdk(b?Ok+t=gz)n9u#m10Y^VWzJD599P(#sP3&X*OBqm0O6T zN(Vp(THuJCtpAq)PLKXom#I=7aa&m=8IAcmEyNQ%?pX@FjGBUzYO)F9Gd)~gUuI@X zty98$TK5r81RGm1Ij}l#oru-p?Y+|1SY~l(k{-)6@~M)t+F<)-g#5KC0s}XkC7p%^ zCdn-4Yw@2??!QF$+dfvoo@G>574d2H`>xWArkwT7=h7qvA77s3KrObj^KyYTd_fA& zc#5kV}AEE?C2Uh+Eg5#ippm!75DCn$WNQf@~c0EFV;RoA?4 zLyO;4^W}(S?R32SD(>4;dfeL<2@R9@f=Yw{;hHyv4!4r|k=ENIwbC%bd899f|0j6` z+$pqZ(qx)43)AiS=$q*YUB{CjU-KDTMZdTG>WRc3?rB&SL5P- zWvpmrT7wZFS8&4^Mw(n+HFy+O(zDB-*(4YHjVC-oBpNL6;5AAs!g1Yl*Q)_eQU9Zm z3qZsINDBNAk=%WT$t?jE*Z65F7q9B^gDI_GgJo36}Pn%`F?(9 zh=?AY=o3{HijGodL&yQDTwfR){e5=|cy1N7e~g z@gh~P4QnBxO%#>~5*W-uWMco$#H6%C-%ZYVB+4j-nRFeHKh-=j3hey>v#JeST#vbK4v#&Wf?q06IdMT(XsTt4VTJACh8)J6EfUk$R_eTqHhu-k%^Cmz;>@db>{`#>#L1Cud)4@i#R^Gg~WGe@d% z4H|kqcKKZ$=6*CFdwLl@7DxEITP@R7QmB*|z;g(NNB&vp$0>6ZRuIq+7`G6+fN_(e zU8|4kqVO%xeYjo4!*jQE?7Oyc0Ls3qaG-9+lK*tKtQP8tcEz1(geE^+Q^ohNg{kEH z{=V?lKMDJZavRT9|Hj5}~ zZy&%rYC3dSl=$ZWrv5UsUpGz9<8K~SANb^bSk2cnlW(DjBg~^0lUh?h8X&3=IP<0W z0wn4zC}G0vnI2eUSuddW`cR`R;Lyy&SC2l|2n#^!WSw3;e62l&P2=O^9jYkU^sQy= zzAo#-=f=kft_25**m8$_-7zvgQ04pl)BGuchc~BbgUQV^Rpw>w^S6^%A_Z#X8tx$w zdqP6jDs4SV`yi)#t0C>>+lwSSFoCuSYkv+HT#pIT@VYlK+SNCzn5Yw);;qSV%3rfo zgOgsfAxDTF}S4)Q#J-nqhRhtz;Pd11beKvaj(!{;@Y!NFM-EVsR~;U}ypmeBKJC$&87b zaIkVoZ&OGXcCb47{K%6EyPG8AKRtz0=Dj=Jj_v@&?r8sIZdxY5EKQBc1JN4pm%z?1 zA#^iJaI+*nG+uo4F=3wf<&p9+r=AX)AA5O2Jo+A<_~y;~%D9ncvbP8(b4!kh(A>IW6MRBpN5dvFG=~!U-E=CmX*e8uR=# z>sRE3d9{8CrV8wll&p-3z z2^%YCo2~WahMf2JJQhju_JR9F@-S%W7gmS!FeIq9d=JfxxD~$rph!s^XVmZD%H2u=7!=YteSug{3rJNZ$&tur-8sgs7=-VF?@ zC$a1>98l%urKW0>So1GR%z7{X}Hp z5dF3QZ`ic88h0^isgC)66*2D#RxnB>kP_CEje*}d_wI$gnasEXWPK3Er8Yp|bD0;= zLTzXkUvKedm%nGx=PVDXFORbqC`d%fGF4UQRToBh-i2 zTy9~oU{C>qXtGH>)wm?~>O~I|S_4Gm5I1)ry{BhlshrZaG8#R{S2?^znj$_bif^ln zv`l6Wu^S9TlaFI7N`ps?M>Xt$QeyKyrqcbRBR>yP4=P0Z!fM?=)+!UJ`*%hrVp-PH z=qkzlqzEJ(oORZGCMa(k@VAPfjmopIX$H{AA}<>avn!rJi}x$S)@|6Q+Pr zWCq1Whj?LR=SRd8sC<+&>tIz{>ugzk%cbzOpE1Dz z0Aho+zXlUp#SLz-W<1HI+H-_l9!i2#0M+hEL z+RX$h$cG_9YomFbAex1{)Jk+Fs{~U%tr!G$&f6Uj^-~r6McExZKtYfOrhfnc@m4Mb z*Qu1Vn%k_atYp@F6-?(6C-DY5pSVh0CKNdmtCEEmcWX?)_6fj*AsC#|EYf&Q#eD$-YpMH0d!n!OS(c_-OxT z{k9-!(@T@@UGwwa8^Z<&2+H-~K2P`Cgw7WC|3&&1RzXTm)iW@3)jP0aSb2JSLFsK7 zd$%jR*+^Yj_;sfDEwFc^u6OphKvRfXL;1LxY`k2TBF))9Za%h zVuv`w|+p7Q>Z39funnkNI287uz6IoFPeHYS?ZjEbg#A8?Jr( zOuX^5*BE8WFFkHYtLtlMxTvG6+eV_~vojhXd5-X)s>!#JjUq-qs4es@25WkiPv_4+ z(q#d|BeRd$G+2WZYwbgS6cicA)qeVyh@ed7sxl(!v&!Vn$whrQy`JSy+u8TF)I~~o znNrmp8N?gw-Y9WhhEVp{a=6a;D*sq3$>o%maSRB`q8c=*uy2Z`=hCS%$R><`!HDm^ zgMdM)#wo{q^U=g)8i?1v;}pC96FG@op(kiWg3l_&^>rMR0>MDy<^5jeL;6cIIL7d} zyPt^)M$7*P^z*~@T&2{L%?#kHZhlzt2VdR9g1v_y=%h!bW#l`Te#p!O6&p;&2!oJa z(HsST76l4hJ zOg0%|PD+=JN-4_w*k9LQ=Z3#d5&m0k^FS`{&pfFS<6Ak1bu|R zpQOM43bv4$DRT0?O}Tmco%rvz$CU(7szIv^QnBk}STH$XOB^9G7r~+661pvI6~n=8 zJKy|ABH%>K*fPR^YN!iN*LgY*qWaqFZg4;G`C_p&m|cs*&eW`~x~|5Mct~rXt_34_ z^cdSj^->mKO)m%fQj>vUC6Mgk=(M9dCVx@d?OI9yS&Zm*R*pfI)eXiGeNk}1J z>AWK&%w=_ifpzF5y&dH-a+m%(R*!>i2;A!WtcE^|L1B6O(L^{opNsizY5L0mj}0p5YkSi zg4KmqU&}kw{(^E(l3}1m61^cgmn`#jCG)O7t;Hb%QVZl!?$C*)Et3p#B*>Qli301w z_C9yt<^Je;Pk^Z@oi34NN1wSTJq|r``CU>#13qf23^6JnEhn?yB?6c%nmjohVeK=y8&y-C{lIm}0d`UZcC>86H#A#1BPy#GI{ zm0gp2>^QxotvT&mlQoxuBU?-OGP2P-r#1B1wjERj3=>3;J#*@0UzMmN@E0#E2%Uvf zOO!r498R^f{FKeiq~B~0BhVi>PpqkJ!3~9GILcm%^Q+Wdl%+UOa-i?XcFJ!P9T|6K zy}hoBgJJmZ2?$Dr-?`PeY^r>nFl#ZH{MLu*#d!XgW4?SBxrC;lCz=e3j8#X+ zeU`l#7eZUjupfu+u&lnaOJ+4r$fI0v4~_tJ8kEe!)jH;KO6R|ln62)~bDv=xRz$&- zgS&WwrSl>;f-0cc5yl=$CLqZ>wgDCUzGv#jI>fQpzazNE?P%p+h`1P6>UTxo1=A_}L=vDLjxfO8W9GXd0nuWBSO{#8;6fNPE4=kn}A-qnfe`$$OI=p(v&4DtYsJ_N8?W}q$t9{~- z*g&D z(Y9qcc7=`kou&{zdA63mNf*HEMcRrYDl(cl#!ta2E>B`MrOhZ%Zkz|< z=k(%_lL%(20z5wgygwq9il%%VvouHQzoPyC6+$Lk9zxwZoDva|#g~p@4defVrpi`E^_tZxC>nKzu3N{G;8r=?wWR4=Gzt0wn^a5_N!xM#{~>h%p!r~s=hQlF@O zT>EA7zO;m-zBjDN+6{L22~#>jn#nxJ!aDZMvk2t1Nrfsio21*I*T6Ui0rDW-8VkMw zVZem8Wh$i|O-t=%#j)HbD9mM%+KWRLY@XX5nIK~6V@Ht-bQ6_v37=UCi?CCbRD~Jw zmpQh|@dup;A|wOSY~lNPhd|rgmw+Qdh`U>`EkpD^@G{w2963Zp$_g}v`+#Zd_Zvrg>b{z)WD ztz+BKU_uT2R!MAr^UxTJ(96P#CXh!?Lkb~pC6Cm7mXQQi;~BcK)eHa@*?MRB0{X8F zJvS?{y$uS$Ix*owAog~JdooL_$i9gH-7nck+O2y{D%4V6#KmlDxA=G>23z7B-paDo3EGyOe(58>2oMFH{uBlRZvKP^DS zz&fR!;X0U+b$*LcYB8J@f1=u?e=CU`GOJ;^RYexCD=7h9dzj=h1eFB~u{=x4%VtUm zFG?*Kv#W^@$`gk38@R|V3P~HOK-t>udj?Mp#S2hJ+wH#3#uswF%G&9A@(Mx1wgV>o zXG2p?C3l+e*StHp^sA*uXXAq(XOJAFp2NRVX=zOD zr57Va{=MT}gpso>(ir?(N(-k_?$zOJ;&^F`q!!MAq4fXONX|LY`6W}AxZ!`&pHvMl zov5C?Lidx)h#rP40`R)Lt5my3VvWDZY0gPfOJ>R;k&|EK8NtdpZha{9JgjkYnCBGJN7CF%bYU z3-NeQ(JIc1x1c&2|M1N+&3l+&hwkffYY}CpNYY&Tg45YS6V;o;CcJCh6e@0R1!!0` zICDvC062=|7O1@}$GahIO2Bm@CF;k!y`8|EKx!$1N;0b(@{Ix6nNpkc`4LbIqc7Cnwn!T2`cb_b!APwo-N9=`8Y9R z!$TiJ58)t0K#>-?|Ecno)uV!EOkyk+{g!7=$e*K^DglJM&ZZ&|_03bX=%}&9qQ}yJj9y_Bd*U#zerwdX|myhhG~@HV-* z`JD1;vxd6`mq3m!9cuuR8OgKhQBjg*`&#^1U-2XI%;n^koLZdHZgE5=%x)#JsGH$& z%2)YVxBOjZxx1I9PuRa&8yK)$)jMzHIA1+#ng=aq*Lih$n;ZkxDsE&0X|ry`rQsVQ zy^?5@WuyCIfyetV!o8&gAb420=v95$(`Vjt=6N}9kXv6OFGSZ2$YYshSeZt6C(|yW zWlA~2(TCs_5P)zPD>{xTd{#KvwHUK}AkKn%5=+qy4EsAe4-q-Yjch4RHr8xRI1FR# z+e2_eq<84Ou}UGOY;rQOt|CWm@SIxd*gQ5tdgk>qgSlkCNmvW@hB*CbMT{Y+iL#XG zpWzLzl2kg)3MVaflu={?9i`>@OF~(8APUq8MZ3*FRS@CpgGE_^GqL4Iz|1j!v8c=Q zbzbliZ*(6#qsB_cGkZ>GAB+mAdDz=U#=l!@b7#snVJ0g!~4SC;nt zAy1G@#c8J=x%nkJoq|G@`lhJv;LdTN$%h8j;1U>NA$@YC$B2K`G}Cr;+Neb`Qdq-G zzWLy2@|V{+wiNELZ}N|)o^tb@${`Eao696v6QdVyL+YMm&#_CH2c86E>KSi_l%47T zm0RV0+VT{=6*YD&tq3M}e!LQH4tX{RLM*x#(euvq$7N$JX!6w>w)R3ZC0HJcS%|zF z=|=HO?%MoD{Z0`7^ledI~|hfqXD{gYBr!IC*bKa-mP{8EY^z6p6fYrt_r+L_(gbaE7Tl8|z+(HY(_3x-Cq}e})75nAf)>u$XnpD_2U`^wD zFG-&pdDnW#Nf8>@N_sCNtI1r)!~B0`uh67Gaw^FxL}3{QV7zfSo-<3sF7L! zPiT;CI2HNXpo0l?6XzBdHBCm>iP#Hgj{PUk1+I7>vyW+gBvhG3tk|dP*Oq`;pi73x zIIz7P;7)(TlW|(yC&WMz^Y9Dwu;zg%3Vd-^`?m+DojjK=-BXP&2i5A6N0(=Rgqs_@ z$b|mpttg97zyzM<%|nAql27k*1ep$U(%>cZ_075ngI~PpQ)M(=R_kXn9OvX22K85! zwEyHAMX;p1B^s5-gm6l_jL$9G|K?EE6$ZdYm3qb@N}1rQr|5 z&tX`qAyP-bZ~{qH@$idfoJ-GQlE)aSxG3J`M{0-u`jtN?L9u+xYH#sP@NWm?HwxWUs`ngRCBHgJ+g2_n3mR2z}3wR|9b10@wiXNjUlSP!%x&ME;7 z<~_)R8~_EE{ES-e(q%y3Urq8$Hhk=K^eU8q67h;)iK58d9WnO+H%D=!WT{F2#bMrm zXjzbL)L7j-1~OUzDW#Uw6}H&fHOP2W zd^P+Eok!*v&=x0dS&LGL+33yWQcL8l7$~?CIIQCJX6Kaqn_r>LVt>7@3!D-b@CKWS|PnWvf;Uq_Hh*j1)pC9k3d9$3w(-J=omW(%_1NX zM5^LO{CU}@qs;w6sDhp{sEYAh12tmALh{$mD2I`%5U4h!ieCB{NXGpJN&cgcfum|b zhp?9la6}}e*H@EXO0HA%UYws#Au(`2aTM&<`jNg(M$)lq!BN&_ zIfY0QW#4?p_$O`983U8N(FsUgz*&*Y#yo2V94Kdg7CIt58ZxLLjnJS3=xO|aWPJ%d z)cODaI6_gh+9--H)g~%(Gdgr^VcS-cV-U%@iE)q8A#!D-a&5=5sVK_L5Jicpl%c`6 zCkEr1gSq~%&kWxm`=7_|KH7ck%=`0sAFtQ*^?W^FueX>Fk9&`gL%-yUoE037xp7k< zN>gFE0=WT4npqtB-W+b?IwU3)_;2DB|3smJ~ z!>%EL>XdKDCxBWHZVMEQ8f6O}|LQi=+e!_1hb@h(?R5d^L+!wE{Am4bhkw~gDDaDp z!S$jCMc_sL=TB`i0KuPJ$nt4 z62>1WaZxado?HgmIpovPPfY-=34;5e4?DzU{$-cWL*X109FGV@#i{=+b8-W@5Kt35p9<^cq1ytCYWUpi7;^fpS_hf{Ixc}u#Oo;Em}@V){M zgxfb=e?I?R#Q??$oaR92a{K1Rr-6DeSUJ3n-_@NkTABZsNVd>Xf6g!z=N zU9?A9MoUafHD>jxP5Br54t_m+<es%WDur+nS!?sLoC_~%nc3Hpp@GybW01_Vm~=fv@Q!}{MS?5BB{ zz;8@C`y@6f!B{k_YJ7hPpUhWsr&Za4-IwQkv%T`4L741k{6VwyIN4*b@f}%qa(0tz z_9U?K!Z4*rD2;RaBsbvl4j-0MLto~Z0%#Y=<3jai{w^EX`4D^NxEnE{n}$@B%H*%B zVcSy;9`%Vt9SxUvaa*~$XV8$Rs*B?W{7&XV1Q7= zeSMrLYID!|#HgZkg9&NXd$5%=*8l}0`8-TRU|1g}F+B!Hm}mOFGn_^(fQ7wDDu6U7j?1>Q4JS*2&D~qy7$jr=q9TTO1=Np#I(juJhle%%Gm%nVP z{It4a!+5+6gajLqHWAqVYGUuV#HJJsBQIm_uH}MC!t`*BsfGa$eibD86Pkrj4tW4& z8f;_%lwo4D=dT_B>>%N-3TIig=e7QUZNi*{d8?wOEJ|PBM{Z-uP+NMyG?{xvok!%$ z@rT4EgLWZASpp&mt*9kaTaKD+v7A-F|JA#n7&m{IRH-k~!C0)dwp7O`3#*gfK_a{Z zeh~Z-;0K1!i&F)eL(?JObM`tW$3edUAf*J``$5(#$Z$g&5MrQ(1M07M@XXAP8Ux{8RUS_%Nt*R1J}INIy7S=+2MMuIJ(*I9kO9=}nS zx}Odvj-y$+lk5@F@pH&jBKM%i?7;sdGp21}KEEN+=g`YRg~DQyLC`czo*euq@GiXla;O4Ix+qin3aRbAEK27$02WB=41Z(Z?{N2z z|1_wO)yWJsgmP(PD*7P2MxfmmUc`&cT%27Nr@!FikMG+T?5t|~OENG!;4R`rJdh0L zzI$75?)=O1YeX@Tx*XTh8TaUG;85JPw>_rd-Kl`{sCl%>Lp5YW;zZj*jD})~po;WPcV8 zCbj%)U=@0&B1*4M;W*RYb!@bUnVer;4-oX*v#=?S0pquhV9IK_N9p2x>=d#OY)3eh?EJ4=? zkRGPMARqEzWzD;9;u>^~^erRbYhIZ9n)|;qnvT!Lnq*5m_9)(Qy$3_*<((Wi=ilpnh1&s)tdx>eAU(% zo08HT!w5^Ek04h5iljICf8iN_X8v=h!5s3;j4B7-I^2HC(8;FLcK$XCz+O&%B1#!R zubqZ@|ApPK450eo%5Y1Hr`UGtwr||!BhpTVU z)tbJW={&VEVHHH~DB(9^T?3_jA`#`s_POd;Q>Do9T+QcocqG*BA>v3(%KZY4=_#d-)F=3giV6g3ZURyFP(3No zJ}>V(-wmaAyw(R#CVHsw&*27C5Z zqv346=SKQ1ONXaS$%R?)^%EEe-3&?p@JX8U%RQIVpS5oMCLry_y*#g#=YyW>2_CW4 zj{ckj6Wv!G;XK$*JF6Y1Ro5^_d$1c0rUl;eE^lQHq|#=~JJ}=I3YpLQ$MWk1_6eaK zB_azFd83+*@nrt#otjm43y9bDF}3`oThS{<*PCP|j2ICCry-wzgRh>*o$_In3)SPO;!mDB@*CgmRZMI+4%Hws z)y})&KpwEUut)ivOyNp%;G=;!`-&03la37eU{W!A`xKnuk@C_2lyB#phd~!s$vI=h z9(OmL&r@)nWt7B#t~Ai@E#5XDU1*)d3sSa695xv}iZf}=HR+-X%iU4!2cagQY4FRz zn$;uQ)>*0n)WS9Xtjzp`luAI#Z*ODqt3$8@H1caUnfRy~8s;LU77|iX`lAq6r(9w3 zL^vZyxFyx7nt60A3#KR8icxj z6;D_49m1;YxFyvZmaG;P3!KrU!NPp}2I3E-AlrZDfvY`H&8J9*+3;}3VNcI%`BaGL z)=rllxU4)9Kxt`7pqN9|-}%myoq=849B~>~3pF6B#vZTQ3r;Vzs+*VSh0e}DpHamA zj%nJh$;#6%slto~U0DoK9ZC#K`$jrhT=cyr^mLiSeAri$3T-5&XVr@v4kl<4~_=NAW}n0w%roHacO9oD4E!k!R4^dht8^v$lD8v3VHz zu_MaDViZ}EOJtb8ol0w|ozo{Y36c)1_~D_7&8H9~8*!EsCYnecxm*3CJhFg0xfLu0 zy7@exK|ay;qcVa)(sytZVms4S16rj})_wc3asI$Ksz)|`^&WqPyV^McR!@| zwK@~GoLXZBlqX9;yvFmy8jyUH=acvyU9yfv3Hr5E!;F! zC}Utx+)Tt7d;2^0lTWK~Cqur(VUj1~Ehp!MqoWGBr>79%H9+c{7gy>4VT<(rvI=n+ zJSKzK&hzYcQ`E^~y`Yit^i`dK_Fz`>sBj^d=rdy6wSkjA!Y~82se`=77|pg4!#PEVSnhgieZ%!9>^u5+x zOIxW%=m;h-jmk$^APEAha}4k30qLFDa1G92BS01e-9J)Asclz}9HED@5i8D4xl)l| zWQsbf_pL;|iF>m;O!GsP9=dEVVJeYl-Ob;C$$CrbRu3|aQWDw^B)IY5R#~7qkEZHX zSocPa#_l<23SpJ01tbqDDt6ty3~XK74ZN!jq+V=filH5fJJJEgRwiN8$Yf*u@2eyj zFE67M{qefiP~s8&&=HG?ij$5YWc>(Z-1%6knD{ScQ;rC3!Yxv-gx`*Jv$7VgSb2X= zP-Z3!<1|V-c73p${zkq}tsXQRUU}VN`@%E4i_COWV)QfA({P68qn&iPAyHDCZ1&w`P zK0meJ#FbD=^E+=qqdO0aV2&YoBJqPfZi3$oxVw%ze=-{1cRbpXaanmd@*Rj35voqF zklpFHrxBbIpqHy-!Q3x__cYhC$7BYia{sl=J&o)T8OiDEAG;H)Zq|n3TmJkR8?0&@ zx<9jOXSLc~Y?Q9+`WGMq0li6oXnsjWVRgrC7PhO}`t(A)JODruf(kH~Kenxtx$z|L zgLBfO@75JXMdu02Y|s1nW)U?8pn+ay<_2jIC>cri%;-*EE7*;D_bRrxyH|4~ar{^p zWU$0Kc-IfR$@FhFm1E6sjw7dW&YSZUB3WB~Iy2cDOL@c#&jQ1AXZUFNE8_e)@O=X@ z6%xTt_r!pofckIoqy88r83}gXB}XOT?-7RP01{g484$-O7wPT~)?Cq@uAEV?WK@&v zFqjYE1tVnb{BgGn+^biM7W8ZP6u-CUGyW+XJ6gS~YxGr&-^xWck{we*%03w|rW=9H zpB?czL932?qDK>+h?@6>6&2~Q{^A1{-)u_MO?Y!r`@==;LOB;(#wu&8J3t=X5O}UT z@e@+%`GhRF&f>91^-AXE4~L{mla5!1ouYM|4rk`ftuSe?SNu1UY+eTSAa}d?4C;2n z7xK`vg<6Un11hJ=f#HtZrdv7Ty3U?0P7xN0p!6O9T0*KwlOAG|@jgshFQB4_LsWHt0^PlwauLYR@GZ>z&D7rcn} zioY_>rCSfB(%3n#u$_nw{(lcpSRK7fC8Yt)mkb!B;O$3fS8r7BVkYhUm@#&+SOJa3R!wbBsgl015PboqRo-lV69=wzHiU1T zHE~77B4qYX%b4)de6Ju$dFM^X#M^zjk!WBsA+~XlF5IoK15AV$>6}bL7oa{wCy#8G z`UcylR%hNvN>z@Ozp_souU2uhRFp_y#0G@~dMeezonJd6_2k;j-Q^hucRZI&%%O=Xc3+VxT=(?-vrPIlmulb0Pl* z=^c$UhwP-l;T=cnoUT7gev1M*yovnZEm?};4DDX7FRPlrDuWdFrK#dH*0!hdQV)HE=J0;U@dOtbU1K(@dsw9)y zAUr#&jCMF5Kt1e5>HGnGN1FE4^?q`GF*W_Zu@Bp`pREG9vGVAJ$s$~L z#Z*&w+?%3)r`D_b!>7Yk6s@Ip%ZaKyA1Y>2+K>g|-@v6P_s#wQY2E)Z1Uh6YLbG+U z-lVw(H`A5;YPT007d}JJ1S|w&XV?H=mBC(O}*nU_;SnURSv6m;BTdq!6lH1F1&GqkDhm(|gIVL0>z zibs(?Z3ys_t!$o@M;qye6HfRK7iEow&jY?u50VbzwnSCa^^^ULHpYEv%%RcjHPR5| z*Q4|-PKf)^N-zbUESKJ*?NYS2Z`cR?h+{tGP&fJh&p=PVWmLm^%+YK@RwIeVr0Hf_ zf0Ew5<(G5dQp4XS4i=|X@8}v1L!=1N_^vyU+Xfsws9@Ye->p%mPULpc-k+}?P5-j% zSBkrEn>u2Mfl$MeGb-YF7xd2WT?)~9QiTr`HUSL>VY#DD+ZUI8?;ZENKz3Z7p;e8B?pm&5<9`_M=#J=_>4Ia|edutdtb#5pPEYC<;}y0mnS_~p z7(U^Kxo=l*)htZp>e6(q5mGpgeV)!Pn<~THZooCfX_fZ^C0{-5o3}l`m~;X?097IR)T?;UuhV0}M&0N%F+>j|cY3+(F)oie#Nbm@DEZdh zOJ}^G+oQajO^r&5CUu ze;FSLYmKx=i4aPnpgVlj-7~BQ&E1^2&bdS6td4Yt?Y!pYtF~JskpvJvaX75WTz>!; z&2cLmkVkigtPzgTI2#!R9f8DSeQRLa{(L>vzFBhhLjnKdnZ3;8Ikg;!KwydITpwiz zSY{dw&aM@&f$KW7d-~@NQL>1Yzm#xU%nP$ECEjMN1yo9hghi_?|6e=yZp{ya1YV`f zp_W5A$mN0XsR>2YCeR(x6#6!f(L)8olT<$Rm$F^CDIhUJttrks2ruz8A;W$C~3> zx;i>0!+~!SOkw~h?Oc;_L5P(%_cPz{n>lVPuQ~Nb$}T8dBKkG2eT(nkZoEH{Jx6Q& znZUh06Z>Ws+E62(QdP)9BCQ?tOrvWZ`IE~O!Z7=wXZ~vib_*rov!?BX9kC~&i$@ul zG3Ye1Qje-A%AZzv97-@m7AW>`;&2d{BwOg~JH#|7AHQxlO(!Qm&0^je{`sGP`Pv!Z z+WR@H$7)27b`tbZguRKDZlltnco}LB)Fo_6j7?#Kc-boGt7?>@1gFfs<|vEeJ<>V- z6rDzLU_AT-H>DvUF0t$!o`<;TP9m`{6KEQA>FHj(Z6cv6fPGmK| z&_uB5p+079^s}b!?5ds;_w@>^oSx2vRmmKEgrsgrs-li4l=J$DBb*NEFIaA$C54ea zSNjz==M5FxWTdizT6&=sDm&?xANK=IY)8L_$?A6eVJ9V+K-7S$Nz>E3Umr`sa1KzF z4jml{S6&A{|Ag>Pzmkd}41Sp8RoMd|^H;$5VuGtxb41*xHR$)l9H#R+8U5sx!3v(Q z*Z<%vUA!Lur~$o`7(Q0wGf*`x2Q)B;Zwb~{2VxbQK7L}CUtm4HjFysN$8gV1_oyBsP5qn5mTvJ74r{t< zI-n{q?`kX1hKkIA+T5+JM#Pbu@Xet0C^B|L7-oJKo)8!i@88Ch{MhG#Mr6C(cJf`mqzxN_2T7 zh-MNj1xf!L%iE9IiAC7S#A2`3;^$_)hqFs0qYpsR{H>rINLAq{ORrGVZ=HS~CafaO zCP~a>zdMchH#BoW0t|$@?>m(?^g)wFDjV{^8`m}1Q9I|YvGP6GD3h{>IdQ0XPrAd` zocz{TP|M=?S@u{VboYn3%?7|U`b-LZ%&C**9mAcoap+809#zGhUY%ZlRS-pk<=Pj@ zNttRdV5Qp8iTKUj_X*R&qBNB6huEdo;sf z@S(K85KBGX_$$$siRGUd51vgN>gLal3>abd#o=U`vg*)G3-U62GtB`VOXF#qkkK?; zfCm4W=COhuh+rA{L~VfN_AZN+)NNGbY7>@PugO{udYbS ziWQuTr+5}MU^q82sBoLgC(o`BN#TQ7{4G${?iN4HInk!^J1JepF4gt+V=|4Do1F4m z<&x$EWGl^E?~Y5Cv7X==mB1aKP@5YK&Ne^SrLTz!J?j##B1j*+wJ(9SJ+%$q+-TaQ2i099SzCN-El?CM_%`z z-3GQQpITp?6di|%jIW^(uj}%>@7Z(dSLGVHI3|9e1;a`!qv-PR&%Phg147U^S<@*doday}qTm+Eow&!WA?g8{+3unS-#q;2h;;ACH(0yP6`v zOwE4K>51yycn8D!xoiX)q+CxdYbz5M4&7*glPDGRlYSdzch<8^;U~Dv3kzW{^gBSW z=#IO}9B*P=QEt&DZ)Hk{QOk8cD9shx30&!`dD0%*Q5{5=)G$;FT;+ji`PjDpK?>PWpI93NVAQ7)iwu};k76`J5I%2 z!WKDIrHzubt^&y2@yp26ZE8}K2T*~(VHQdiUwMV$vzclf(FTuw8*_IwaVh%3_Yc^B z_ufmW;?u1Ih?-SKxfr&G&FeA70s;X&NBIadVB|b{r*$MRZ7`M+=@&b^lOn7ug`DY3 zNYD6qzTR?wr%9U2zT^HErV5Or#_)vg$9-`A6Jik2aVu_ocPm^TX3-KULt9oICgKC_ z1c-rbCm&*<4NxPpEPfOn%88KjV8O09-1++5NIE&i5H~znMg>GZVoX~DfCb4iXb#0C z_=NwO&+@?B--YHk?F;Yh&s3V<4)NMZ4O{%Rs0{w&uT}3MZQEFPWXjEQt%>1J&{>Sh zrgvZJE#i}Jr0aw;2D&oNe`No5fF_nZ9b{j^=ZBoE3o?>4&qaEE>=jNCXuf}WR~W=vU*qr3LBU|D=DCdW zt!c*WY5%tvu5HUKg3|Q${I?+y=fLb1Z-@*{12(`2un?5)FOi=F%>!-yIk~?B?9F!!CTG z<%XXLtxKi^3D?tcmlZU4bavX*V+5o-msNr^atZ*&icNOhC8)h+_XvD#j2z45t@G33 z=20eYJC;AUD}aCtwHlG-JQ3Cb1Su1zK3fk$!XrcLGY!Mac%D78YyJ$Ogkl9b-;LLS z7pijtWCrZaaBD8;5nPOOc&j9%WsYu%6G2MCQTn};XJMhx{G;Q%cwBZEe;U^~)#alg z;6b{ckv516mWM!*u)EEQ4D2!&{P^YvZw&<_3?nAL0<}) z$rm}4i$c)gTqyZ(H}nQs%RFuKX#zRryFf+tGW)L+CWD%=LbJ~x=Rnxbt)@6HVA_GlX81t+?30FYl)vZ$$J0 zN4`d$eKk^^v6e4d^Ab`k`hg>V8T%n83bpx|;ZNV1Y43-L+#?ovo^HS#pFgHuLf*`S zM0^5uOZQMup2yU`maJEHbI;r;x81n^$P|=yr`)8Rop&O~Ik$XYp93+{EAy1L$C$M$&TPl2ly@JRSq>hL>4}!kbTK>k~vHWMW14{N`hk{JTPs7xOpW8^E z#O;Mx=Y7g$%5MwrlRX1P2+*c~^T7lSL`@B`@EcUkUd4GHS~!XeNu2IQBXD-((`Idf zeAlhkDAKLc=yKM0(;Q^U?HWS1#XTeXus;2kn=8eg@bO6^UwWN=ShQpXcsrywm&13&WG@inh2xpFgzK~i+JjMt zD1P_5r1Lj%75Poz`5IJF$}a_CGo+mt3W*V;p5aE-f(_AQRam!4Mu`hg(&yvobDxhK z+3vez{v4yZOL@YUXrk9))N>7jhD1_cFyeZM9gRI10~_E5gzK7O?B1zwx(1xA~$>*P_N z9R!@N#(okjg)=8RlWYYam*Nf>iUK_e1r>fB@ya%hcZi`-I!^^kvJDP@TY3-74caZ1ryVoBr`}5B%vH+j}ml z^$KiCUEXeuDx(xxcEG*J0WGbNsiWOYs@r4qz0lv5&wH+@4E8Hf3azt^=?wqTUa`rSXencX45@$)P^_7 zx1e{Y7yg+ZfA80dCzCXT@PaD;q|bES3!M7g3*r5z_m%hV1Y`N+p3$uPPK~P0==y+l z!q-ij=6k+)Lj7ufzHr9?>-?kPOLILeEK;SpRtn{>eHw=i3Q`vrc(nRI99La%_N8~D zTl(zzhHy~0CzUzf*ndK4=1+V=FlW4=0ON1kYwN$(IRr#pCw3)$mN!v%*Pf~nC|6i`N ze@pwJgx>Gv%gj&SD=*oP7@8!_iQ(?giRtE64}$s&zwH}5(OfYzdzND8V;M#nvw8iT z#avz2y?JoZI;WEJL1tr^y@a)W3J4h8eChkwnJ~&_@+0je5<~1Htc}zr)$UO?3)e&S zDD!i033{xAY9KA@@eo3LwUis2PUtEIu0PQRrRM@-8OSRg6keRYy2mSjsD;GDy~1{9 z4MmsyQ{CUDg|DVYyIYb|7&BeN<5h-`&ibc{IsS^-9dSVZx{6M{@fG|7dhEWpk2K8r zr_yptXQtNVY8;>Z_XL3xKKux#&D!Jwnz36YVvtubnKAEPpFyNgxQcIb^_03!{|pou zh$=TGPWxuVwcOGvUx&v3d*%E|KxAZ zS>F1VC3YFJK7n_s3u| z1;GUTfjc?#5l7MwRGTmkbe~Ik60J5j&m0t%Wv?zqWR3uWmtEcu!pGC8u26Ya$IF7w z5YXaiElT+c-iFARa z^CHUk7^NRrD$5No_WybUzNJ5(K}ok1&Z$|T6V!sMu4aok zT9Y(yqYM#M$1>88tl;9 z5B20ZYt51!3a}2@!&v*Yx6ZwLSE3{@0?jR`Iso}{5nre)Q9pJv8wY@B=j5UGPQ-;AkPUsIUfmy z#C!tC2&eb7X|Fgi<<2-%2xD5Km{?XXDk12K>bpJ0&F@Em5Z!to7o$B zHhUJ*`{jA+`%oFVAlHMeSd$QCHr`luWm&@EQR++K`lALa`|;&ET=_!%Fws@O;zDE3 zp$M^>GRTEP;030`S!mA&I-?y=U%A;czuu~9JW-XAkeUEs3M(1U5{^6q5q+G9!15D)kx3?cpnYt*oGLb)RUB{@s&mZ~+rHlDsfXPjt`W zH7DzVJS=5y0sp)8wil`jKgx~L0{~#j%@8++{zqWhW z3!gs9v&Zd$ATMdhlI|Esv7EDa0m?qFp@+(V3*-Q}-NXz1$$;vXUf39IUeb1!Bh2|U z_5@snxAQHKQqDd)LXsvZJ*CEn^YelXI_f=BA%(Vbhk+B>cd45NB zJe+{KY$S9Q*?!o@fwguH1isqwX5y;bL-4Mr*1*FvR7H{G32O7-^Jl%M24Y`C2mJhP zR68v>pw!V6I8?bPc@MA?+Uq;e%LOw%KLSb_xi1Owp=Z^v;(bL0w{&o&=YR?@1JPg% zDnk$QqevmH>qX&v&VR3_*1(Vh)gWudE&hJE!ylLiDD{Ft9szF;WI{u~bak-Al5d!9 z+{77!ecz#8h|%i+t$qj}EhtWllQgyXodt{ogTGGTS{5FyM-?;(;F91?P%U9soCI2o zwX34!oqz`35i9VQ0{c1tg(&5BUooc*FB>_|(PqWL*8Bo_uGjkvmEj(ldNL#~ppPW` z;5y-CFASpJ;8>8C2h}dnB3tSOEj)MKxIGjE6w@ourn*90A6k{QOhjO37QW%H*h>?% zzmVsN%EGCEbS`0*33@Sv%ap8X%aSKhDy0O6Vc{#j)r_1=_rES5SnZrU9b$nr!dw~k z+)%+nAYhiCcLNKraR{!h6!ba1^A@$S4I~9+7V^vt(Hb43MkD?R@Ih}dODF0#C`ttd zGL$HwHlDIcrR?WI&MQu$<_L8g+%+?-0NpoUsG>w27oG?1CJhI72{#vgTAq>8>l@r6 zFAL@7%fuW(W5Ctw^}%ODvfzLqJXrWn)FEiHi(FF&OhobXWg;!_FKQc5me+tx14(y@ zB$-#Xn+Z}J^XF;di+VpHRWrYw#$BEc%15-*zR;gr2i#ec-~bEuzhDc`f1&3G_~8yu zHO{gY(%cJiKwW5_79PqMnxFk@WrgTfQ3@_b_Xh0x$xwBmh_WHN;{j*DmWO)=vqnjuNgdQT`yEgZWK#E_3KLqP^5K{bPlYk=RpzDTLHu!IRO(9v-+Fyq z`}qxz$H?#fw}1al)HLDLoe}SbVS2V$Bn`S;V z(hanyTr%KNrPT$L;lenmsrS9KLiLc4koV>J5~AVlgZ{^DQVR@l4h{}*>yGEoTweK@ z^^EkAT|8QAL|AuyQ@`GN310=XQXadB8%hZ@fVM#PJqM%HmOjMm}5pn>-e)Z&fS4!3!w`YEpzZFKWI8}7w1OgKMRt*eb1pVOb&!ipGE3tc+S z^Jmoif%el=Q@7u?VN|nAxXk@ZYl(r)dt@XeOg-n8Endl*)8|sR_3K?wy#9>(r>d#R zu9`nd46EL6Mg&-#PpIIc)3;BbdYn)F1FrH?U%70_KGXXvBn!yCPpepeX4-Y@}mS|Ri^ z@2aV=Q?e~`TL~-i=wi3ulKA6R-vH?Z z+Dk_+v8+)yUaOygCx4DNtqz?Ahf*+C)vE2PeDsi5@Ii1DJ7Tl5*O{GCT(QKGZ6ucG z-^{+=N{SS5y_46wOr=;M_?j^?Nhn zT4O6KDEInj$BJkX0T5aEb|c^GvvR}U2r_*29wR)Gp3@L$ua)rV!655%NsLlfzfA$$ zS%U1MZ2W}^%_V-VhGyRSS2azGP~?Q_@RxV7sp1{&!oUt16Uh%D73U91Xr!G0+z*qK zI!IA*_VmB;30_%HFEk0)zfDqv-6{mtS;l3^F_2o{%*$7O&$!~Ed0iGr#&)` z0YvJ4SDWfN&iaPWpH}6&-(O?4NxeB}@&d16s10+71D!^+WGvv8gnfi*0^g3f--Z|* z-x%OE!=3clj9Gd}+4m^=5oEXfYIP_bYpZWh`^f`@=D~-b`!Ulw?&4QF7-p&==TY|u z+)#5&JTdWkEm}u{&x-6P2HzbukkD+JqP*q>KB5g@`cR&qWrafMqlM4Jz3WbL1d$5F zCe;)X<37$d@QZ5|mimc`TR2$$ zNbm1r?a_I8{$+OEmr|EUC64)*adddx{i53}6$*J=G%o%suH-d~RyzTF*1DB^7G0%w zB9T1J#Oq+YuW<4Tm;}u!O$mRfoZEn7Mh_>K`GGvb|}wv1|67mxjY!poj`vZbgFL&JUlH0MLI5kd9bTXSS# z)lsO4;GvL~rlvS(5Od;eyLS8m<&PykPyHYtes_~yg?YKwde#-V_WnGxkIrCb85sP0$ z53XX_x9ZSizkwdxgSe|#5cDBxNBkDlF1E7?Ek>)H+$O0!c`nW8`;59M@aT)({Ki@^ z+A!r({sUfka3lFt>``3Zp7vGg{a3rwng*LG8PqUnRW=Y>6&oUgTI|Iqj3PaaGASK< z8dq=m1Sq0Vom{z`fjvCYFgZpl(Ovdn+Nh#hGU6RM^mzx54f&GA;fN}272+|*f|?4| zB@QMOk3kj^dXtsxc|i-?#JQZ$w=Jk(G4Gm`&sytcm_PJFEj>9AlQivw;koV{lU4nH zJ)Wf%lk>`HiMzqD0ydgeZJ|u3Z>|#(n6C6>5 zEdG}JHma#GrfpT9e;K&=lFSf$H($x{acVhlLdS-%A1)?9&9fA+e_vpm3PIL$veiX# z)B%e7@*teT%>_(OO*!{SmTm72ML%o09bzLxbNpUhbz*}5ISR>aE!usm7&(27gL*-u z06=dUkqZauTRiJb67ur8E4fyknTNbXBB`(8tSmMd`pz6Sm(2vwq&WKfsWmVtWqP(r zH|TpzW?enrr;7(5Z7szip?H>=Ws8p(2PO|msLg*I)8M2sY2=kxM)z~P5b%o&VWn>c zS05XZ#D)c~o-F{wI+pC`qX)my z1O7EXPq(3~1%Dn+|LJ0WKK0L1)RHx;85#<)ATxE+Z&$sIu(FEywI>aGWGZv4{f2Lq zLqKSM>JL|&`Y!#pI1%vQCLXQ2OTTWa(|z$fGh!%2M<(b&US75muBd2t$D0~%7@-Q@ z4uO!G4ILBEL>Nt{0e`pnoaksF__u_9d({0AW%$x}`=}BDkc|85y!b#!L!4ZFS7Jmw zPz{SPe$6Jp>eVzeAJ2S*AcYqK0gXL#MOWvHwbe+De!UJMB+LHAC~nv2YypMpnBf`Y%2iwJ7N#vc0YA9RBcDO4G znrwV8j)?I}uqVE4E%F%~oXST9-&fN-q89^~DO-I@i;SG>6klpcr>k3W!iOd&8iW>pg~lNPB#IQ(@^R zL%d`Gky=sk9K}-nUfeZ0D2hz>Vzx&WD|H7>4MeR@6Hg#dJR5FtYK^QCU+pEAiDLF1 zEq+{t3$*ts=IYLB?NboJaX*SI!HfgRePjUtq_ZD#e?gE5G~>C!KiA+lV>H$Y`y8wO z!)&?!VX1Pu4cuU`^tq=ln+_+Ud2+u@J`qTLcgFVZtnPNdZ#T1{!l8gxt-!9vIt(e2 zAlae~y5uEK-G^a4EmVga(6iJy=Db_D2ER*_MP&1@w3Ua_T>ZRc{o~;Z&Q-WrlBiGjLk&42OlIU~edcOB_J~lbW7@i^0Py47yE?uhx*9F!hx-+1uPr#<= zXz-?Ps5?R{urCPBWWSsE>mVK+kwNw6H_%Pasfwp!bzQ&dfdmrg5;a zf{*$CHZ&g5AIRq?haLILyj2Rf<)`M_;>&G;nTdxpiuvQV0VbrwK)o+ETObC_@}<&_ zZvJ3Y%fOIKm|^_2W|QOiNJR-^P($oP)~6s!J1XO-G;is4a7+YW1|>CspI9$It84Y` zhUf>kknu*1^EFL_Kc#1?5b2>^UNdFtanf4>wJo-Es7cK-H≷Nw?R>K_MpgF!PD~ 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 uXO|lHkJkW9eVT5a|vnL68n% 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 z zW`e|#TT-&wqj8f%MK^R2GO!hBMNbNJw6#;W@1laFV9dyWT?hqS%UO~@>0U-6tg!aIMQ`Al*I!&g>4bt~V)#+^plJ3{ zS9W3*MwbES(cof3T^%22$}f>`xNZ%Z6DALmx8cDe4}Xfqs3_%lnL=T5ce1gO^T0#3 zibF(}xM!uON5j{w!j+0ogf0S#YM~}2JX!&ubn{XJvoBj?vJmJ zkI_2;+gor=bhP0S5ue$z>}+jwYioID#89X`YbYU5Ra3Wt(!O+@eduS|%Sr^#o@pVY zqM~A(#e*DoaB#5x0u3b#kSrW52qx7Dj&i_6@pVO-V_3{7V-=%gfh?WnHXIDo}I&8pAB0s7A9@^#s57 z-=~dvDAcSQX!zFP-JUr+JG56lqppX~XLdd#ZzK?ivj zM-*I7YSt(JGtaW}@;?uuN53$geHi#I<@V=4+ApBJ2`H?V(BZ@%6n#9z>*AycF=f3b!jV62$DkM*x%l)ipNy=DzXcMi7C4YBB23(_sW63TMZpP2xyQC zTgcXi0POS*F7`kSgp8sz4bv3h&o%S(C`5O`-eI5?=!uO@(sq;zy} z@b7fvXUV0k!}8!$xll7nNnhWyZrHEDEzp%V|E^F69JqoI4A0$w7MlcS`ON`cLKCGn zfr)w*ufRwMgrKUvJ~`OmhQM3*^XE_MW=Hta)3Y;b__M98^>tl>xnOvTv0*U_Rh`~@Z6=mau|T!KdSk7o{?g}Oq>a7#PftuqYhHK=haCgT=iV zJX#hPuW(U2pZoj!J4Z%Frq|Zi+;dczo52aooZ5Flgc -> [!NOTE] -> Tomato is available on Google Play in closed testing. -> -Please [use this link to join the testers Google Group](https://groups.google.com/g/nsh07-app-testers) -> and then -> -install [Tomato from the Play Store with this link](https://play.google.com/store/apps/details?id=org.nsh07.pomodoro). -> Tomato needs 12 testers for at least 14 days for the app to be available on Google Play publicly. -

@@ -33,12 +24,15 @@ install [Tomato from the Play Store with this link](https://play.google.com/stor

- - + + + + +

@@ -100,24 +94,20 @@ translating this project into languages you know. ## Download -- **Google Play Store** (recommended): Tomato is available for closed testing on Google Play. Use - [this link to join the testers Google Group](https://groups.google.com/g/nsh07-app-testers), then - [install Tomato from the Play Store with this link](https://play.google.com/store/apps/details?id=org.nsh07.pomodoro) - and help Tomato to get an official Play Store release. +- **Google Play Store** (recommended): Tomato will soon be available (currently in closed testing) + on the Google Play Store. + [You can find it through this link](https://play.google.com/store/apps/details?id=org.nsh07.pomodoro). - **F-Droid** (recommended): Tomato is available on the official F-Droid repository. Simply open - your preferred F-Droid app and search for Tomato. - Updates on F-Droid are generally a week late. To get faster updates, you can install it through + your preferred F-Droid app and search for Tomato. Updates on F-Droid are generally a week late. To + get faster updates, you can install it through the [IzzyOnDroid repository](https://apt.izzysoft.de/fdroid/). -- **Obtainium** (recommended): You can add this GitHub repository - on [Obtainium](https://obtainium.imranr.dev/) to get updates directly from GitHub releases. This - is the fastest way to install and update Tomato. - **GitHub releases**: Alternatively, you can manually download and install APKs from - the [Releases](https://github.com/nsh07/Tomato/releases/latest) section of this repo (This - method is not recommended, use Obtainium instead). + the [Releases](https://github.com/nsh07/Tomato/releases/latest) section of this repo (This method + is not recommended, use Google Play/F-Droid instead). > [!TIP] > To [verify](https://developer.android.com/studio/command-line/apksigner#usage-verify) the APK -> downloaded from Obtainium/GitHub, use the following signing certificate fingerprints: +> downloaded from GitHub, use the following signing certificate fingerprints: > ``` > SHA1: B1:4E:17:93:11:E8:DB:D5:35:EF:8D:E9:FB:8F:FF:08:F8:EC:65:08 > SHA256: 07:BE:F3:05:81:BA:EE:8F:45:EC:93:E4:7E:E6:8E:F2:08:74:E5:0E:F5:70:9C:78:B2:EE:67:AC:86:BE:4C:3D From a0235cb1178135a2c7c0226a028c3c9e6f45b204 Mon Sep 17 00:00:00 2001 From: Hosted Weblate Date: Tue, 28 Oct 2025 10:27:20 +0100 Subject: [PATCH 24/25] Translated using Weblate (French) Currently translated at 100.0% (71 of 71 strings) Translated using Weblate (Chinese (Traditional Han script)) Currently translated at 100.0% (71 of 71 strings) Translated using Weblate (Ukrainian) Currently translated at 100.0% (71 of 71 strings) Co-authored-by: ezn24 Co-authored-by: savoie7304 Co-authored-by: vintagezero Translate-URL: https://hosted.weblate.org/projects/tomato/strings/fr/ Translate-URL: https://hosted.weblate.org/projects/tomato/strings/uk/ Translate-URL: https://hosted.weblate.org/projects/tomato/strings/zh_Hant/ Translation: Tomato/Strings --- app/src/main/res/values-fr/strings.xml | 6 ++++++ app/src/main/res/values-uk/strings.xml | 6 ++++++ app/src/main/res/values-zh-rTW/strings.xml | 6 ++++++ 3 files changed, 18 insertions(+) diff --git a/app/src/main/res/values-fr/strings.xml b/app/src/main/res/values-fr/strings.xml index 4ae182d..e4112f4 100644 --- a/app/src/main/res/values-fr/strings.xml +++ b/app/src/main/res/values-fr/strings.xml @@ -64,4 +64,10 @@ Son Ne pas déranger Activer le mode ne pas déranger pendant un minuteur de concentration + Couleur dynamique + Adapter les couleurs à celles de votre fond d\'écran + Toutes les fonctionnalités sont déverrouillées dans cette version. Si mon application a fait une différence dans votre vie, veuillez envisager de me soutenir en faisant un don de %1$s. + Tomato+ + Obtenir Tomato+ + Tomato FOSS diff --git a/app/src/main/res/values-uk/strings.xml b/app/src/main/res/values-uk/strings.xml index 18260d7..6b782fa 100644 --- a/app/src/main/res/values-uk/strings.xml +++ b/app/src/main/res/values-uk/strings.xml @@ -64,4 +64,10 @@ Звук Не турбувати Активувати режим «Не турбувати», доки таймер активний + Tomato+ + Отримати Tomato+ + Динамічний колір + Адаптуйте кольори теми зі своїх шпалер + Tomato FOSS + Усі функції розблоковано в цій версії. Якщо мій додаток допоміг Вам у житті, будь ласка, підтримайте мене, зробивши пожертву на %1$s. diff --git a/app/src/main/res/values-zh-rTW/strings.xml b/app/src/main/res/values-zh-rTW/strings.xml index 832677b..ee44adb 100644 --- a/app/src/main/res/values-zh-rTW/strings.xml +++ b/app/src/main/res/values-zh-rTW/strings.xml @@ -64,4 +64,10 @@ 聲音 請勿打擾 在執行專注計時器時開啟勿擾模式 + 獲取 Tomato+ + Tomato+ + 動態顔色 + 調整主題顏色為你的壁紙顔色 + Tomato FOSS + 所有功能在此版本中均已解鎖。如果我的應用程式改變了您的生活,請考慮透過捐贈 %1$s 來支持我。 From 7051c36366b50c63e949dff1ea43437564e00ba9 Mon Sep 17 00:00:00 2001 From: Nishant Mishra Date: Tue, 28 Oct 2025 14:59:59 +0530 Subject: [PATCH 25/25] chore(release): bump version, update changelog --- app/build.gradle.kts | 4 ++-- fastlane/metadata/android/en-US/changelogs/17.txt | 5 +++++ 2 files changed, 7 insertions(+), 2 deletions(-) create mode 100644 fastlane/metadata/android/en-US/changelogs/17.txt diff --git a/app/build.gradle.kts b/app/build.gradle.kts index a396eba..713c0f0 100644 --- a/app/build.gradle.kts +++ b/app/build.gradle.kts @@ -43,8 +43,8 @@ android { applicationId = "org.nsh07.pomodoro" minSdk = 27 targetSdk = 36 - versionCode = 16 - versionName = "1.6.1" + versionCode = 17 + versionName = "1.6.2" testInstrumentationRunner = "androidx.test.runner.AndroidJUnitRunner" } diff --git a/fastlane/metadata/android/en-US/changelogs/17.txt b/fastlane/metadata/android/en-US/changelogs/17.txt new file mode 100644 index 0000000..cd66b44 --- /dev/null +++ b/fastlane/metadata/android/en-US/changelogs/17.txt @@ -0,0 +1,5 @@ +New features: +- The app can now automatically turn on Do Not Disturb mode when a focus timer is running (this needs to be enabled in Settings) + +And other fixes. +This update also contains a new paywall system (For Google Play only)