From 7375e5c89b78829b757daf8be950af8525cc2148 Mon Sep 17 00:00:00 2001 From: starry-shivam Date: Mon, 25 Dec 2023 13:02:05 +0530 Subject: [PATCH] Improve code quality & Update dependencies Signed-off-by: starry-shivam --- .idea/appInsightsSettings.xml | 45 ++++ .idea/deploymentTargetDropDown.xml | 17 +- .idea/gradle.xml | 5 +- .idea/kotlinc.xml | 2 +- .idea/migrations.xml | 10 + app/build.gradle | 25 +- .../com/starry/greenstash/MainActivity.kt | 15 +- .../greenstash/database/core/AppDatabase.kt | 6 +- .../greenstash/database/goal/GoalDao.kt | 6 +- .../greenstash/database/widget/WidgetDao.kt | 7 +- .../di/{MianModule.kt => MainModule.kt} | 17 +- .../reminder/ReminderNotificationSender.kt | 31 +-- .../reminder/receivers/AlarmReceiver.kt | 2 + .../greenstash/ui/navigation/NavGraph.kt | 236 ++++-------------- .../screens/home/composables/GoalLazyItem.kt | 5 +- .../screens/home/viewmodels/HomeViewModel.kt | 7 +- .../info/composables/GoalInfoScreen.kt | 27 +- .../screens/info/viewmodels/InfoViewModel.kt | 14 +- .../screens/input/composables/InputScreen.kt | 16 +- .../input/viewmodels/InputViewModel.kt | 13 +- .../settings/composables/SettingsScreen.kt | 74 ++---- .../settings/viewmodels/SettingsViewModel.kt | 61 +++-- .../welcome/composables/WelcomeScreen.kt | 13 +- .../welcome/viewmodels/WelcomeViewModel.kt | 12 +- .../com/starry/greenstash/utils/Extensions.kt | 13 + .../starry/greenstash/utils/GoalTextUtils.kt | 46 ++-- .../{PreferenceUtils.kt => PreferenceUtil.kt} | 36 +-- .../starry/greenstash/widget/GoalWidget.kt | 11 +- .../greenstash/widget/WidgetViewModel.kt | 11 +- .../configuration/WidgetConfigActivity.kt | 10 +- build.gradle | 15 +- gradle/wrapper/gradle-wrapper.properties | 2 +- 32 files changed, 379 insertions(+), 431 deletions(-) create mode 100644 .idea/appInsightsSettings.xml create mode 100644 .idea/migrations.xml rename app/src/main/java/com/starry/greenstash/di/{MianModule.kt => MainModule.kt} (85%) rename app/src/main/java/com/starry/greenstash/utils/{PreferenceUtils.kt => PreferenceUtil.kt} (76%) diff --git a/.idea/appInsightsSettings.xml b/.idea/appInsightsSettings.xml new file mode 100644 index 00000000..5c682537 --- /dev/null +++ b/.idea/appInsightsSettings.xml @@ -0,0 +1,45 @@ + + + + + + \ No newline at end of file diff --git a/.idea/deploymentTargetDropDown.xml b/.idea/deploymentTargetDropDown.xml index 5dd2abd2..0c0c3383 100644 --- a/.idea/deploymentTargetDropDown.xml +++ b/.idea/deploymentTargetDropDown.xml @@ -1,17 +1,10 @@ - - - - - - - - - - - - + + + + + \ No newline at end of file diff --git a/.idea/gradle.xml b/.idea/gradle.xml index ae388c2a..0897082f 100644 --- a/.idea/gradle.xml +++ b/.idea/gradle.xml @@ -4,16 +4,15 @@ diff --git a/.idea/kotlinc.xml b/.idea/kotlinc.xml index fdf8d994..ae3f30ae 100644 --- a/.idea/kotlinc.xml +++ b/.idea/kotlinc.xml @@ -1,6 +1,6 @@ - \ No newline at end of file diff --git a/.idea/migrations.xml b/.idea/migrations.xml new file mode 100644 index 00000000..f8051a6f --- /dev/null +++ b/.idea/migrations.xml @@ -0,0 +1,10 @@ + + + + + + \ No newline at end of file diff --git a/app/build.gradle b/app/build.gradle index 45672751..fc963b09 100644 --- a/app/build.gradle +++ b/app/build.gradle @@ -58,7 +58,7 @@ android { } composeOptions { - kotlinCompilerExtensionVersion '1.5.2' + kotlinCompilerExtensionVersion '1.5.6' } packagingOptions { resources { @@ -75,16 +75,18 @@ aboutLibraries { dependencies { - def composeBom = platform('androidx.compose:compose-bom:2023.08.00') + def composeBom = platform('androidx.compose:compose-bom:2023.10.01') implementation composeBom androidTestImplementation composeBom // Android core components. implementation 'androidx.core:core-ktx:1.12.0' + implementation 'androidx.appcompat:appcompat:1.6.1' implementation 'androidx.lifecycle:lifecycle-runtime-ktx:2.6.2' - implementation 'androidx.activity:activity-compose:1.8.0' + implementation 'androidx.activity:activity-compose:1.8.2' implementation "androidx.lifecycle:lifecycle-livedata-ktx:2.6.2" implementation "androidx.lifecycle:lifecycle-viewmodel-compose:2.6.2" + implementation "androidx.navigation:navigation-compose:2.7.6" // Jetpack compose. implementation "androidx.compose.ui:ui" implementation "androidx.compose.ui:ui-tooling-preview" @@ -94,22 +96,19 @@ dependencies { implementation "androidx.compose.material3:material3" // Accompanist compose. implementation "com.google.accompanist:accompanist-systemuicontroller:0.28.0" - implementation "com.google.accompanist:accompanist-navigation-animation:0.33.1-alpha" // Material theme for main activity. - implementation 'com.google.android.material:material:1.10.0' + implementation 'com.google.android.material:material:1.11.0' // Android 12+ splash API. implementation 'androidx.core:core-splashscreen:1.0.1' // Room database - implementation "androidx.room:room-ktx:2.5.2" - implementation 'androidx.appcompat:appcompat:1.6.1' - implementation 'androidx.core:core-ktx:1.12.0' - ksp "androidx.room:room-compiler:2.5.2" - androidTestImplementation "androidx.room:room-testing:2.5.2" + implementation "androidx.room:room-ktx:$room_version" + ksp "androidx.room:room-compiler:$room_version" + androidTestImplementation "androidx.room:room-testing:$room_version" // Dagger - Hilt. implementation "com.google.dagger:hilt-android:$hilt_version" - implementation "androidx.hilt:hilt-navigation-compose:1.0.0" + implementation "androidx.hilt:hilt-navigation-compose:1.1.0" ksp "com.google.dagger:hilt-android-compiler:$hilt_version" - ksp "androidx.hilt:hilt-compiler:1.0.0" + ksp "androidx.hilt:hilt-compiler:1.1.0" // DataStore Preferences. implementation("androidx.datastore:datastore-preferences:1.0.0") // Gson JSON parser. @@ -129,7 +128,7 @@ dependencies { // Crash Handler. implementation 'cat.ereza:customactivityoncrash:2.4.0' // Oreo back-ports for API 24 (N) - coreLibraryDesugaring 'com.android.tools:desugar_jdk_libs:2.0.3' + coreLibraryDesugaring 'com.android.tools:desugar_jdk_libs:2.0.4' // Testing components. testImplementation 'junit:junit:4.13.2' androidTestImplementation 'androidx.test.ext:junit:1.1.5' diff --git a/app/src/main/java/com/starry/greenstash/MainActivity.kt b/app/src/main/java/com/starry/greenstash/MainActivity.kt index f9ec6be8..b3d6e697 100644 --- a/app/src/main/java/com/starry/greenstash/MainActivity.kt +++ b/app/src/main/java/com/starry/greenstash/MainActivity.kt @@ -45,13 +45,12 @@ import androidx.compose.ui.unit.dp import androidx.core.content.ContextCompat import androidx.core.splashscreen.SplashScreen.Companion.installSplashScreen import androidx.lifecycle.ViewModelProvider -import com.google.accompanist.navigation.animation.rememberAnimatedNavController +import androidx.navigation.compose.rememberNavController import com.google.accompanist.systemuicontroller.rememberSystemUiController import com.starry.greenstash.ui.navigation.NavGraph import com.starry.greenstash.ui.screens.settings.viewmodels.SettingsViewModel import com.starry.greenstash.ui.screens.settings.viewmodels.ThemeMode import com.starry.greenstash.ui.theme.GreenStashTheme -import com.starry.greenstash.utils.PreferenceUtils import com.starry.greenstash.utils.Utils import com.starry.greenstash.utils.toToast import dagger.hilt.android.AndroidEntryPoint @@ -77,12 +76,14 @@ class MainActivity : AppCompatActivity() { override fun onCreate(savedInstanceState: Bundle?) { super.onCreate(savedInstanceState) - PreferenceUtils.initialize(this) settingsViewModel = ViewModelProvider(this)[SettingsViewModel::class.java] mainViewModel = ViewModelProvider(this)[MainViewModel::class.java] // Setup app theme according to user's settings. - settingsViewModel.setUpAppTheme() + ThemeMode.entries.find { it.ordinal == settingsViewModel.getThemeValue() } + ?.let { settingsViewModel.setTheme(it) } + settingsViewModel.setMaterialYou(settingsViewModel.getMaterialYouValue()) + // show splash screen until we figure out start nav destination. installSplashScreen().setKeepOnScreenCondition { @@ -92,7 +93,7 @@ class MainActivity : AppCompatActivity() { // refresh reminders mainViewModel.refreshReminders() - val appLockStatus = PreferenceUtils.getBoolean(PreferenceUtils.APP_LOCK, false) + val appLockStatus = settingsViewModel.getAppLockValue() if (appLockStatus && !mainViewModel.appUnlocked) { executor = ContextCompat.getMainExecutor(this) @@ -121,7 +122,7 @@ class MainActivity : AppCompatActivity() { if (biometricManager.canAuthenticate(Utils.getAuthenticators()) != BiometricManager.BIOMETRIC_SUCCESS) { setAppContents() mainViewModel.appUnlocked = true - PreferenceUtils.putBoolean(PreferenceUtils.APP_LOCK, false) + settingsViewModel.setAppLock(false) } else { finish() // close the app. } @@ -159,7 +160,7 @@ class MainActivity : AppCompatActivity() { modifier = Modifier.fillMaxSize(), color = MaterialTheme.colorScheme.background ) { - val navController = rememberAnimatedNavController() + val navController = rememberNavController() val screen by mainViewModel.startDestination NavGraph(navController = navController, screen) } diff --git a/app/src/main/java/com/starry/greenstash/database/core/AppDatabase.kt b/app/src/main/java/com/starry/greenstash/database/core/AppDatabase.kt index 1824d977..a5f4c7a0 100644 --- a/app/src/main/java/com/starry/greenstash/database/core/AppDatabase.kt +++ b/app/src/main/java/com/starry/greenstash/database/core/AppDatabase.kt @@ -25,7 +25,11 @@ package com.starry.greenstash.database.core import android.content.Context -import androidx.room.* +import androidx.room.AutoMigration +import androidx.room.Database +import androidx.room.Room +import androidx.room.RoomDatabase +import androidx.room.TypeConverters import com.starry.greenstash.database.goal.Goal import com.starry.greenstash.database.goal.GoalDao import com.starry.greenstash.database.transaction.Transaction diff --git a/app/src/main/java/com/starry/greenstash/database/goal/GoalDao.kt b/app/src/main/java/com/starry/greenstash/database/goal/GoalDao.kt index 41a0beab..3ebe689e 100644 --- a/app/src/main/java/com/starry/greenstash/database/goal/GoalDao.kt +++ b/app/src/main/java/com/starry/greenstash/database/goal/GoalDao.kt @@ -26,7 +26,11 @@ package com.starry.greenstash.database.goal import androidx.lifecycle.LiveData -import androidx.room.* +import androidx.room.Dao +import androidx.room.Insert +import androidx.room.Query +import androidx.room.Transaction +import androidx.room.Update import com.starry.greenstash.database.core.GoalWithTransactions import kotlinx.coroutines.flow.Flow diff --git a/app/src/main/java/com/starry/greenstash/database/widget/WidgetDao.kt b/app/src/main/java/com/starry/greenstash/database/widget/WidgetDao.kt index b6a4b3ac..6ef80717 100644 --- a/app/src/main/java/com/starry/greenstash/database/widget/WidgetDao.kt +++ b/app/src/main/java/com/starry/greenstash/database/widget/WidgetDao.kt @@ -25,7 +25,12 @@ package com.starry.greenstash.database.widget -import androidx.room.* +import androidx.room.Dao +import androidx.room.Delete +import androidx.room.Insert +import androidx.room.OnConflictStrategy +import androidx.room.Query +import androidx.room.Update @Dao interface WidgetDao { diff --git a/app/src/main/java/com/starry/greenstash/di/MianModule.kt b/app/src/main/java/com/starry/greenstash/di/MainModule.kt similarity index 85% rename from app/src/main/java/com/starry/greenstash/di/MianModule.kt rename to app/src/main/java/com/starry/greenstash/di/MainModule.kt index 396e9439..2de4e2ae 100644 --- a/app/src/main/java/com/starry/greenstash/di/MianModule.kt +++ b/app/src/main/java/com/starry/greenstash/di/MainModule.kt @@ -37,13 +37,16 @@ import com.starry.greenstash.database.goal.GoalDao import com.starry.greenstash.other.WelcomeDataStore import com.starry.greenstash.reminder.ReminderManager import com.starry.greenstash.reminder.ReminderNotificationSender +import com.starry.greenstash.utils.PreferenceUtil import dagger.Module import dagger.Provides import dagger.hilt.InstallIn import dagger.hilt.android.qualifiers.ApplicationContext import dagger.hilt.components.SingletonComponent +import kotlinx.coroutines.ExperimentalCoroutinesApi import javax.inject.Singleton +@ExperimentalCoroutinesApi @ExperimentalMaterialApi @ExperimentalFoundationApi @ExperimentalComposeUiApi @@ -51,7 +54,7 @@ import javax.inject.Singleton @ExperimentalMaterial3Api @InstallIn(SingletonComponent::class) @Module -class MianModule { +class MainModule { @Singleton @Provides @@ -66,6 +69,9 @@ class MianModule { @Provides fun provideWidgetDao(appDatabase: AppDatabase) = appDatabase.getWidgetDao() + @Provides + fun providePreferenceUtil(@ApplicationContext context: Context) = PreferenceUtil(context) + @Provides @Singleton fun provideDataStoreRepository( @@ -78,11 +84,14 @@ class MianModule { @Provides @Singleton - fun provideReminderNotificationSender(@ApplicationContext context: Context) = - ReminderNotificationSender(context) + fun provideReminderNotificationSender( + @ApplicationContext context: Context, + preferenceUtil: PreferenceUtil + ) = + ReminderNotificationSender(context, preferenceUtil) @Provides @Singleton - fun providebackupmanager(@ApplicationContext context: Context, goalDao: GoalDao) = + fun provideBackupManager(@ApplicationContext context: Context, goalDao: GoalDao) = BackupManager(context = context, goalDao = goalDao) } \ No newline at end of file diff --git a/app/src/main/java/com/starry/greenstash/reminder/ReminderNotificationSender.kt b/app/src/main/java/com/starry/greenstash/reminder/ReminderNotificationSender.kt index a5a596f4..ee3c7247 100644 --- a/app/src/main/java/com/starry/greenstash/reminder/ReminderNotificationSender.kt +++ b/app/src/main/java/com/starry/greenstash/reminder/ReminderNotificationSender.kt @@ -25,20 +25,16 @@ package com.starry.greenstash.reminder -import android.Manifest import android.app.NotificationManager import android.app.PendingIntent import android.content.Context import android.content.Intent -import android.content.pm.PackageManager -import android.os.Build import androidx.compose.animation.ExperimentalAnimationApi import androidx.compose.foundation.ExperimentalFoundationApi import androidx.compose.material.ExperimentalMaterialApi import androidx.compose.material3.ExperimentalMaterial3Api import androidx.compose.ui.ExperimentalComposeUiApi import androidx.core.app.NotificationCompat -import androidx.core.content.ContextCompat import com.starry.greenstash.MainActivity import com.starry.greenstash.R import com.starry.greenstash.database.core.GoalWithTransactions @@ -46,39 +42,30 @@ import com.starry.greenstash.database.goal.GoalPriority import com.starry.greenstash.reminder.receivers.ReminderDepositReceiver import com.starry.greenstash.reminder.receivers.ReminderDismissReceiver import com.starry.greenstash.utils.GoalTextUtils -import com.starry.greenstash.utils.PreferenceUtils +import com.starry.greenstash.utils.PreferenceUtil import com.starry.greenstash.utils.Utils import kotlinx.coroutines.ExperimentalCoroutinesApi + @ExperimentalCoroutinesApi @ExperimentalMaterial3Api @ExperimentalAnimationApi @ExperimentalComposeUiApi @ExperimentalFoundationApi @ExperimentalMaterialApi -class ReminderNotificationSender(private val context: Context) { - +class ReminderNotificationSender( + private val context: Context, + private val preferenceUtil: PreferenceUtil +) { companion object { const val REMINDER_CHANNEL_ID = "reminder_notification_channel" const val REMINDER_CHANNEL_NAME = "Goal Reminders" private const val INTENT_UNIQUE_CODE = 7546 } - init { - PreferenceUtils.initialize(context) - } - private val notificationManager = context.getSystemService(Context.NOTIFICATION_SERVICE) as NotificationManager - fun hasNotificationPermission() = if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.TIRAMISU) { - ContextCompat.checkSelfPermission( - context, Manifest.permission.POST_NOTIFICATIONS - ) == PackageManager.PERMISSION_GRANTED - } else { - true - } - fun sendNotification(goalItem: GoalWithTransactions) { val goal = goalItem.goal @@ -96,10 +83,10 @@ class ReminderNotificationSender(private val context: Context) { .setContentIntent(createActivityIntent()) val remainingAmount = (goal.targetAmount - goalItem.getCurrentlySavedAmount()) - val defCurrency = PreferenceUtils.getString(PreferenceUtils.DEFAULT_CURRENCY, "") + val defCurrency = preferenceUtil.getString(PreferenceUtil.DEFAULT_CURRENCY_STR, "") if (goal.deadline.isNotEmpty() && goal.deadline.isNotBlank()) { - val calculatedDays = GoalTextUtils.calcRemainingDays(goal) + val calculatedDays = GoalTextUtils(preferenceUtil).calcRemainingDays(goal) when (goal.priority) { GoalPriority.High -> { val amountDay = remainingAmount / calculatedDays.remainingDays @@ -145,7 +132,7 @@ class ReminderNotificationSender(private val context: Context) { } fun updateWithDepositNotification(goalId: Long, amount: Double) { - val defCurrency = PreferenceUtils.getString(PreferenceUtils.DEFAULT_CURRENCY, "") + val defCurrency = preferenceUtil.getString(PreferenceUtil.DEFAULT_CURRENCY_STR, "") val notification = NotificationCompat.Builder(context, REMINDER_CHANNEL_ID) .setSmallIcon(R.drawable.ic_reminder_notification) .setContentTitle(context.getString(R.string.notification_deposited_title)) diff --git a/app/src/main/java/com/starry/greenstash/reminder/receivers/AlarmReceiver.kt b/app/src/main/java/com/starry/greenstash/reminder/receivers/AlarmReceiver.kt index 6ee23be7..160ac7e0 100644 --- a/app/src/main/java/com/starry/greenstash/reminder/receivers/AlarmReceiver.kt +++ b/app/src/main/java/com/starry/greenstash/reminder/receivers/AlarmReceiver.kt @@ -42,12 +42,14 @@ import com.starry.greenstash.reminder.ReminderNotificationSender import dagger.hilt.android.AndroidEntryPoint import kotlinx.coroutines.CoroutineScope import kotlinx.coroutines.Dispatchers +import kotlinx.coroutines.ExperimentalCoroutinesApi import kotlinx.coroutines.launch import java.time.DayOfWeek import java.time.LocalDate import java.time.LocalDateTime import javax.inject.Inject +@ExperimentalCoroutinesApi @ExperimentalMaterialApi @ExperimentalFoundationApi @ExperimentalComposeUiApi diff --git a/app/src/main/java/com/starry/greenstash/ui/navigation/NavGraph.kt b/app/src/main/java/com/starry/greenstash/ui/navigation/NavGraph.kt index 932bc05e..649015f6 100644 --- a/app/src/main/java/com/starry/greenstash/ui/navigation/NavGraph.kt +++ b/app/src/main/java/com/starry/greenstash/ui/navigation/NavGraph.kt @@ -42,9 +42,9 @@ import androidx.compose.ui.ExperimentalComposeUiApi import androidx.compose.ui.Modifier import androidx.navigation.NavHostController import androidx.navigation.NavType +import androidx.navigation.compose.NavHost +import androidx.navigation.compose.composable import androidx.navigation.navArgument -import com.google.accompanist.navigation.animation.AnimatedNavHost -import com.google.accompanist.navigation.animation.composable import com.starry.greenstash.ui.screens.backups.BackupScreen import com.starry.greenstash.ui.screens.home.composables.HomeScreen import com.starry.greenstash.ui.screens.info.composables.GoalInfoScreen @@ -55,6 +55,33 @@ import com.starry.greenstash.ui.screens.settings.composables.SettingsScreen import com.starry.greenstash.ui.screens.welcome.composables.WelcomeScreen import kotlinx.coroutines.ExperimentalCoroutinesApi + +private const val NAVIGATION_ANIM_DURATION = 300 + +private fun enterTransition() = slideInHorizontally( + initialOffsetX = { NAVIGATION_ANIM_DURATION }, animationSpec = tween( + durationMillis = NAVIGATION_ANIM_DURATION, easing = FastOutSlowInEasing + ) +) + fadeIn(animationSpec = tween(NAVIGATION_ANIM_DURATION)) + +private fun exitTransition() = slideOutHorizontally( + targetOffsetX = { -NAVIGATION_ANIM_DURATION }, animationSpec = tween( + durationMillis = NAVIGATION_ANIM_DURATION, easing = FastOutSlowInEasing + ) +) + fadeOut(animationSpec = tween(NAVIGATION_ANIM_DURATION)) + +private fun popEnterTransition() = slideInHorizontally( + initialOffsetX = { -NAVIGATION_ANIM_DURATION }, animationSpec = tween( + durationMillis = NAVIGATION_ANIM_DURATION, easing = FastOutSlowInEasing + ) +) + fadeIn(animationSpec = tween(NAVIGATION_ANIM_DURATION)) + +private fun popExitTransition() = slideOutHorizontally( + targetOffsetX = { NAVIGATION_ANIM_DURATION }, animationSpec = tween( + durationMillis = NAVIGATION_ANIM_DURATION, easing = FastOutSlowInEasing + ) +) + fadeOut(animationSpec = tween(NAVIGATION_ANIM_DURATION)) + @ExperimentalCoroutinesApi @ExperimentalMaterialApi @ExperimentalFoundationApi @@ -66,7 +93,7 @@ fun NavGraph( navController: NavHostController, startDestination: String ) { - AnimatedNavHost( + NavHost( navController = navController, startDestination = startDestination, modifier = Modifier.background(MaterialTheme.colorScheme.background) @@ -75,21 +102,8 @@ fun NavGraph( /** Welcome Screen */ composable( route = Screens.WelcomeScreen.route, - exitTransition = { - slideOutHorizontally( - targetOffsetX = { -300 }, animationSpec = tween( - durationMillis = 300, easing = FastOutSlowInEasing - ) - ) + fadeOut(animationSpec = tween(300)) - }, - popEnterTransition = { - slideInHorizontally( - initialOffsetX = { -300 }, animationSpec = tween( - durationMillis = 300, easing = FastOutSlowInEasing - ) - ) + fadeIn(animationSpec = tween(300)) - - }, + exitTransition = { exitTransition() }, + popEnterTransition = { popEnterTransition() }, ) { WelcomeScreen(navController = navController) } @@ -97,21 +111,8 @@ fun NavGraph( /** Home Screen */ composable( route = DrawerScreens.Home.route, - exitTransition = { - slideOutHorizontally( - targetOffsetX = { -300 }, animationSpec = tween( - durationMillis = 300, easing = FastOutSlowInEasing - ) - ) + fadeOut(animationSpec = tween(300)) - }, - popEnterTransition = { - slideInHorizontally( - initialOffsetX = { -300 }, animationSpec = tween( - durationMillis = 300, easing = FastOutSlowInEasing - ) - ) + fadeIn(animationSpec = tween(300)) - - }, + exitTransition = { exitTransition() }, + popEnterTransition = { popEnterTransition() }, ) { HomeScreen(navController) } @@ -119,36 +120,10 @@ fun NavGraph( /** Goal Info Screen */ composable( route = Screens.GoalInfoScreen.route, - enterTransition = { - slideInHorizontally( - initialOffsetX = { 300 }, animationSpec = tween( - durationMillis = 300, easing = FastOutSlowInEasing - ) - ) + fadeIn(animationSpec = tween(300)) - }, - exitTransition = { - slideOutHorizontally( - targetOffsetX = { -300 }, animationSpec = tween( - durationMillis = 300, easing = FastOutSlowInEasing - ) - ) + fadeOut(animationSpec = tween(300)) - - }, - popEnterTransition = { - slideInHorizontally( - initialOffsetX = { -300 }, animationSpec = tween( - durationMillis = 300, easing = FastOutSlowInEasing - ) - ) + fadeIn(animationSpec = tween(300)) - - }, - popExitTransition = { - slideOutHorizontally( - targetOffsetX = { 300 }, animationSpec = tween( - durationMillis = 300, easing = FastOutSlowInEasing - ) - ) + fadeOut(animationSpec = tween(300)) - }, + enterTransition = { enterTransition() }, + exitTransition = { exitTransition() }, + popEnterTransition = { popEnterTransition() }, + popExitTransition = { popExitTransition() }, arguments = listOf( navArgument(GOAL_INFO_ARG_KEY) { type = NavType.StringType @@ -159,40 +134,13 @@ fun NavGraph( GoalInfoScreen(goalId = goalId, navController) } - /** Input Screen */ composable( route = Screens.InputScreen.route, - enterTransition = { - slideInHorizontally( - initialOffsetX = { 300 }, animationSpec = tween( - durationMillis = 300, easing = FastOutSlowInEasing - ) - ) + fadeIn(animationSpec = tween(300)) - }, - exitTransition = { - slideOutHorizontally( - targetOffsetX = { -300 }, animationSpec = tween( - durationMillis = 300, easing = FastOutSlowInEasing - ) - ) + fadeOut(animationSpec = tween(300)) - - }, - popEnterTransition = { - slideInHorizontally( - initialOffsetX = { -300 }, animationSpec = tween( - durationMillis = 300, easing = FastOutSlowInEasing - ) - ) + fadeIn(animationSpec = tween(300)) - - }, - popExitTransition = { - slideOutHorizontally( - targetOffsetX = { 300 }, animationSpec = tween( - durationMillis = 300, easing = FastOutSlowInEasing - ) - ) + fadeOut(animationSpec = tween(300)) - }, + enterTransition = { enterTransition() }, + exitTransition = { exitTransition() }, + popEnterTransition = { popEnterTransition() }, + popExitTransition = { popExitTransition() }, arguments = listOf(navArgument(EDIT_GOAL_ARG_KEY) { nullable = true defaultValue = null @@ -206,36 +154,10 @@ fun NavGraph( /** Backup Screen */ composable( route = DrawerScreens.Backups.route, - enterTransition = { - slideInHorizontally( - initialOffsetX = { 300 }, animationSpec = tween( - durationMillis = 300, easing = FastOutSlowInEasing - ) - ) + fadeIn(animationSpec = tween(300)) - }, - exitTransition = { - slideOutHorizontally( - targetOffsetX = { -300 }, animationSpec = tween( - durationMillis = 300, easing = FastOutSlowInEasing - ) - ) + fadeOut(animationSpec = tween(300)) - - }, - popEnterTransition = { - slideInHorizontally( - initialOffsetX = { -300 }, animationSpec = tween( - durationMillis = 300, easing = FastOutSlowInEasing - ) - ) + fadeIn(animationSpec = tween(300)) - - }, - popExitTransition = { - slideOutHorizontally( - targetOffsetX = { 300 }, animationSpec = tween( - durationMillis = 300, easing = FastOutSlowInEasing - ) - ) + fadeOut(animationSpec = tween(300)) - } + enterTransition = { enterTransition() }, + exitTransition = { exitTransition() }, + popEnterTransition = { popEnterTransition() }, + popExitTransition = { popExitTransition() }, ) { BackupScreen(navController) } @@ -243,36 +165,10 @@ fun NavGraph( /** Settings Screen */ composable( route = DrawerScreens.Settings.route, - enterTransition = { - slideInHorizontally( - initialOffsetX = { 300 }, animationSpec = tween( - durationMillis = 300, easing = FastOutSlowInEasing - ) - ) + fadeIn(animationSpec = tween(300)) - }, - exitTransition = { - slideOutHorizontally( - targetOffsetX = { -300 }, animationSpec = tween( - durationMillis = 300, easing = FastOutSlowInEasing - ) - ) + fadeOut(animationSpec = tween(300)) - - }, - popEnterTransition = { - slideInHorizontally( - initialOffsetX = { -300 }, animationSpec = tween( - durationMillis = 300, easing = FastOutSlowInEasing - ) - ) + fadeIn(animationSpec = tween(300)) - - }, - popExitTransition = { - slideOutHorizontally( - targetOffsetX = { 300 }, animationSpec = tween( - durationMillis = 300, easing = FastOutSlowInEasing - ) - ) + fadeOut(animationSpec = tween(300)) - } + enterTransition = { enterTransition() }, + exitTransition = { exitTransition() }, + popEnterTransition = { popEnterTransition() }, + popExitTransition = { popExitTransition() }, ) { SettingsScreen(navController) } @@ -280,20 +176,8 @@ fun NavGraph( /** Open Source Licenses Screen */ composable( route = Screens.OSLScreen.route, - enterTransition = { - slideInHorizontally( - initialOffsetX = { 300 }, animationSpec = tween( - durationMillis = 300, easing = FastOutSlowInEasing - ) - ) + fadeIn(animationSpec = tween(300)) - }, - popExitTransition = { - slideOutHorizontally( - targetOffsetX = { 300 }, animationSpec = tween( - durationMillis = 300, easing = FastOutSlowInEasing - ) - ) + fadeOut(animationSpec = tween(300)) - }, + enterTransition = { enterTransition() }, + popExitTransition = { popExitTransition() }, ) { OSLScreen(navController = navController) } @@ -301,20 +185,8 @@ fun NavGraph( /** About Screen */ composable( route = Screens.AboutScreen.route, - enterTransition = { - slideInHorizontally( - initialOffsetX = { 300 }, animationSpec = tween( - durationMillis = 300, easing = FastOutSlowInEasing - ) - ) + fadeIn(animationSpec = tween(300)) - }, - popExitTransition = { - slideOutHorizontally( - targetOffsetX = { 300 }, animationSpec = tween( - durationMillis = 300, easing = FastOutSlowInEasing - ) - ) + fadeOut(animationSpec = tween(300)) - }, + enterTransition = { enterTransition() }, + popExitTransition = { popExitTransition() }, ) { AboutScreen(navController = navController) } diff --git a/app/src/main/java/com/starry/greenstash/ui/screens/home/composables/GoalLazyItem.kt b/app/src/main/java/com/starry/greenstash/ui/screens/home/composables/GoalLazyItem.kt index 94f0dc77..3de96154 100644 --- a/app/src/main/java/com/starry/greenstash/ui/screens/home/composables/GoalLazyItem.kt +++ b/app/src/main/java/com/starry/greenstash/ui/screens/home/composables/GoalLazyItem.kt @@ -46,7 +46,6 @@ import com.starry.greenstash.database.core.GoalWithTransactions import com.starry.greenstash.ui.navigation.Screens import com.starry.greenstash.ui.screens.home.viewmodels.BottomSheetType import com.starry.greenstash.ui.screens.home.viewmodels.HomeViewModel -import com.starry.greenstash.utils.GoalTextUtils import com.starry.greenstash.utils.Utils import com.starry.greenstash.utils.validateAmount import kotlinx.coroutines.ExperimentalCoroutinesApi @@ -79,8 +78,8 @@ fun GoalLazyColumnItem( val hapticFeedback = LocalHapticFeedback.current GoalItem(title = item.goal.title, - primaryText = GoalTextUtils.buildPrimaryText(context, progressPercent, item), - secondaryText = GoalTextUtils.buildSecondaryText(context, item), + primaryText = viewModel.goalTextUtil.buildPrimaryText(context, progressPercent, item), + secondaryText = viewModel.goalTextUtil.buildSecondaryText(context, item), goalProgress = progressPercent.toFloat() / 100, goalImage = item.goal.goalImage, onDepositClicked = { diff --git a/app/src/main/java/com/starry/greenstash/ui/screens/home/viewmodels/HomeViewModel.kt b/app/src/main/java/com/starry/greenstash/ui/screens/home/viewmodels/HomeViewModel.kt index f2159ab7..53fc2341 100644 --- a/app/src/main/java/com/starry/greenstash/ui/screens/home/viewmodels/HomeViewModel.kt +++ b/app/src/main/java/com/starry/greenstash/ui/screens/home/viewmodels/HomeViewModel.kt @@ -42,6 +42,8 @@ import com.starry.greenstash.database.transaction.Transaction import com.starry.greenstash.database.transaction.TransactionDao import com.starry.greenstash.database.transaction.TransactionType import com.starry.greenstash.reminder.ReminderManager +import com.starry.greenstash.utils.GoalTextUtils +import com.starry.greenstash.utils.PreferenceUtil import dagger.hilt.android.lifecycle.HiltViewModel import kotlinx.coroutines.Dispatchers import kotlinx.coroutines.ExperimentalCoroutinesApi @@ -68,9 +70,12 @@ data class FilterFlowData(val filterField: FilterField, val sortType: FilterSort class HomeViewModel @Inject constructor( private val goalDao: GoalDao, private val transactionDao: TransactionDao, - private val reminderManager: ReminderManager + private val reminderManager: ReminderManager, + private val preferenceUtil: PreferenceUtil ) : ViewModel() { + val goalTextUtil = GoalTextUtils(preferenceUtil) + private val _filterFlowData: MutableState = mutableStateOf( FilterFlowData( FilterField.Title, diff --git a/app/src/main/java/com/starry/greenstash/ui/screens/info/composables/GoalInfoScreen.kt b/app/src/main/java/com/starry/greenstash/ui/screens/info/composables/GoalInfoScreen.kt index b166434f..2c26fb25 100644 --- a/app/src/main/java/com/starry/greenstash/ui/screens/info/composables/GoalInfoScreen.kt +++ b/app/src/main/java/com/starry/greenstash/ui/screens/info/composables/GoalInfoScreen.kt @@ -25,7 +25,6 @@ package com.starry.greenstash.ui.screens.info.composables -import android.content.Context import androidx.compose.animation.ExperimentalAnimationApi import androidx.compose.foundation.ExperimentalFoundationApi import androidx.compose.foundation.background @@ -85,7 +84,6 @@ import com.airbnb.lottie.compose.animateLottieCompositionAsState import com.airbnb.lottie.compose.rememberLottieComposition import com.starry.greenstash.MainActivity import com.starry.greenstash.R -import com.starry.greenstash.database.core.GoalWithTransactions import com.starry.greenstash.database.goal.GoalPriority import com.starry.greenstash.database.goal.GoalPriority.High import com.starry.greenstash.database.goal.GoalPriority.Low @@ -97,8 +95,6 @@ import com.starry.greenstash.ui.common.ExpandableCard import com.starry.greenstash.ui.common.ExpandableTextCard import com.starry.greenstash.ui.screens.info.viewmodels.InfoViewModel import com.starry.greenstash.ui.screens.settings.viewmodels.ThemeMode -import com.starry.greenstash.utils.GoalTextUtils -import com.starry.greenstash.utils.PreferenceUtils import com.starry.greenstash.utils.Utils import com.starry.greenstash.utils.getActivity import kotlinx.coroutines.ExperimentalCoroutinesApi @@ -150,8 +146,7 @@ fun GoalInfoScreen(goalId: String, navController: NavController) { CircularProgressIndicator() } } else { - val currencySymbol = - PreferenceUtils.getString(PreferenceUtils.DEFAULT_CURRENCY, "$")!! + val currencySymbol = viewModel.getDefaultCurrencyValue() val progressPercent = ((state.goalData!!.getCurrentlySavedAmount() / state.goalData.goal.targetAmount) * 100).toInt() @@ -164,7 +159,9 @@ fun GoalInfoScreen(goalId: String, navController: NavController) { currencySymbol = currencySymbol, targetAmount = state.goalData.goal.targetAmount, savedAmount = state.goalData.getCurrentlySavedAmount(), - daysLeftText = getRemainingDaysText(context, state.goalData), + daysLeftText = viewModel.goalTextUtils.getRemainingDaysText( + context, state.goalData + ), progress = progressPercent.toFloat() / 100 ) GoalPriorityCard(goalPriority = state.goalData.goal.priority) @@ -423,22 +420,6 @@ fun TransactionItem(transactionType: TransactionType, amount: String, date: Stri thickness = 0.8.dp ) } - -} - - -private fun getRemainingDaysText(context: Context, goalItem: GoalWithTransactions): String { - return if (goalItem.getCurrentlySavedAmount() >= goalItem.goal.targetAmount) { - context.getString(R.string.info_card_goal_achieved) - } else { - if (goalItem.goal.deadline.isNotEmpty() && goalItem.goal.deadline.isNotBlank()) { - val calculatedDays = GoalTextUtils.calcRemainingDays(goalItem.goal) - context.getString(R.string.info_card_remaining_days) - .format(calculatedDays.remainingDays) - } else { - context.getString(R.string.info_card_no_deadline_set) - } - } } @ExperimentalCoroutinesApi diff --git a/app/src/main/java/com/starry/greenstash/ui/screens/info/viewmodels/InfoViewModel.kt b/app/src/main/java/com/starry/greenstash/ui/screens/info/viewmodels/InfoViewModel.kt index 346383fd..9c6dc5b5 100644 --- a/app/src/main/java/com/starry/greenstash/ui/screens/info/viewmodels/InfoViewModel.kt +++ b/app/src/main/java/com/starry/greenstash/ui/screens/info/viewmodels/InfoViewModel.kt @@ -32,6 +32,8 @@ import androidx.lifecycle.ViewModel import androidx.lifecycle.viewModelScope import com.starry.greenstash.database.core.GoalWithTransactions import com.starry.greenstash.database.goal.GoalDao +import com.starry.greenstash.utils.GoalTextUtils +import com.starry.greenstash.utils.PreferenceUtil import dagger.hilt.android.lifecycle.HiltViewModel import kotlinx.coroutines.Dispatchers import kotlinx.coroutines.delay @@ -44,8 +46,14 @@ data class InfoScreenState( ) @HiltViewModel -class InfoViewModel @Inject constructor(private val goalDao: GoalDao) : ViewModel() { +class InfoViewModel @Inject constructor( + private val goalDao: GoalDao, + private val preferenceUtil: PreferenceUtil +) : ViewModel() { + + val goalTextUtils = GoalTextUtils(preferenceUtil) var state by mutableStateOf(InfoScreenState()) + fun loadGoalData(goalId: Long) { viewModelScope.launch(Dispatchers.IO) { val goalWithTransactions = goalDao.getGoalWithTransactionById(goalId) @@ -53,4 +61,8 @@ class InfoViewModel @Inject constructor(private val goalDao: GoalDao) : ViewMode state = state.copy(isLoading = false, goalData = goalWithTransactions) } } + + fun getDefaultCurrencyValue() = preferenceUtil.getString( + PreferenceUtil.DEFAULT_CURRENCY_STR, "$" + )!! } \ No newline at end of file diff --git a/app/src/main/java/com/starry/greenstash/ui/screens/input/composables/InputScreen.kt b/app/src/main/java/com/starry/greenstash/ui/screens/input/composables/InputScreen.kt index 6e64dfde..c329435b 100644 --- a/app/src/main/java/com/starry/greenstash/ui/screens/input/composables/InputScreen.kt +++ b/app/src/main/java/com/starry/greenstash/ui/screens/input/composables/InputScreen.kt @@ -129,14 +129,12 @@ import com.starry.greenstash.BuildConfig import com.starry.greenstash.MainActivity import com.starry.greenstash.R import com.starry.greenstash.database.goal.GoalPriority -import com.starry.greenstash.reminder.ReminderNotificationSender import com.starry.greenstash.ui.common.SelectableChipGroup import com.starry.greenstash.ui.navigation.DrawerScreens import com.starry.greenstash.ui.screens.input.viewmodels.InputViewModel -import com.starry.greenstash.ui.screens.settings.viewmodels.DateStyle -import com.starry.greenstash.utils.PreferenceUtils import com.starry.greenstash.utils.Utils import com.starry.greenstash.utils.getActivity +import com.starry.greenstash.utils.hasNotificationPermission import com.starry.greenstash.utils.toToast import com.starry.greenstash.utils.validateAmount import kotlinx.coroutines.CoroutineScope @@ -196,13 +194,7 @@ fun InputScreen(editGoalId: String?, navController: NavController) { CalendarDialog( state = calenderState, selection = CalendarSelection.Date { date -> viewModel.state = viewModel.state.copy( - deadline = date.format( - DateTimeFormatter.ofPattern( - PreferenceUtils.getString( - PreferenceUtils.DATE_FORMAT, DateStyle.DateMonthYear.pattern - ) - ) - ) + deadline = date.format(DateTimeFormatter.ofPattern(viewModel.getDateStyleValue())) ) }, config = CalendarConfig( monthSelection = true, yearSelection = true, disabledTimeline = CalendarTimeline.PAST @@ -612,9 +604,7 @@ fun GoalReminderMenu( snackbarHostState: SnackbarHostState, coroutineScope: CoroutineScope ) { - var hasNotificationPermission by remember { - mutableStateOf(ReminderNotificationSender(context).hasNotificationPermission()) - } + var hasNotificationPermission by remember { mutableStateOf(context.hasNotificationPermission()) } val launcher = rememberLauncherForActivityResult( contract = ActivityResultContracts.RequestPermission(), diff --git a/app/src/main/java/com/starry/greenstash/ui/screens/input/viewmodels/InputViewModel.kt b/app/src/main/java/com/starry/greenstash/ui/screens/input/viewmodels/InputViewModel.kt index 4f2079c0..81d9670b 100644 --- a/app/src/main/java/com/starry/greenstash/ui/screens/input/viewmodels/InputViewModel.kt +++ b/app/src/main/java/com/starry/greenstash/ui/screens/input/viewmodels/InputViewModel.kt @@ -42,7 +42,9 @@ import com.starry.greenstash.database.goal.Goal import com.starry.greenstash.database.goal.GoalDao import com.starry.greenstash.database.goal.GoalPriority import com.starry.greenstash.reminder.ReminderManager +import com.starry.greenstash.ui.screens.settings.viewmodels.DateStyle import com.starry.greenstash.utils.ImageUtils +import com.starry.greenstash.utils.PreferenceUtil import com.starry.greenstash.utils.Utils import dagger.hilt.android.lifecycle.HiltViewModel import kotlinx.coroutines.Dispatchers @@ -68,7 +70,8 @@ data class InputScreenState( @HiltViewModel class InputViewModel @Inject constructor( private val goalDao: GoalDao, - private val reminderManager: ReminderManager + private val reminderManager: ReminderManager, + private val preferenceUtil: PreferenceUtil ) : ViewModel() { var state by mutableStateOf(InputScreenState()) @@ -83,7 +86,7 @@ class InputViewModel @Inject constructor( uri = state.goalImageUri!!, context = context, maxSize = 1024 ) else null, additionalNotes = state.additionalNotes, - priority = GoalPriority.values().find { it.name == state.priority }!!, + priority = GoalPriority.entries.find { it.name == state.priority }!!, reminder = state.reminder ) @@ -124,7 +127,7 @@ class InputViewModel @Inject constructor( uri = state.goalImageUri!!, context = context, maxSize = 1024 ) else goal.goalImage, additionalNotes = state.additionalNotes, - priority = GoalPriority.values().find { it.name == state.priority }!!, + priority = GoalPriority.entries.find { it.name == state.priority }!!, reminder = state.reminder ) // copy id of already saved goal to update it. @@ -145,4 +148,8 @@ class InputViewModel @Inject constructor( state = state.copy(deadline = "") } + fun getDateStyleValue() = preferenceUtil.getString( + PreferenceUtil.DATE_FORMAT_STR, DateStyle.DateMonthYear.pattern + ) + } \ No newline at end of file diff --git a/app/src/main/java/com/starry/greenstash/ui/screens/settings/composables/SettingsScreen.kt b/app/src/main/java/com/starry/greenstash/ui/screens/settings/composables/SettingsScreen.kt index 3e3587d3..fb7e3e6b 100644 --- a/app/src/main/java/com/starry/greenstash/ui/screens/settings/composables/SettingsScreen.kt +++ b/app/src/main/java/com/starry/greenstash/ui/screens/settings/composables/SettingsScreen.kt @@ -80,7 +80,6 @@ import com.starry.greenstash.R import com.starry.greenstash.ui.navigation.Screens import com.starry.greenstash.ui.screens.settings.viewmodels.DateStyle import com.starry.greenstash.ui.screens.settings.viewmodels.ThemeMode -import com.starry.greenstash.utils.PreferenceUtils import com.starry.greenstash.utils.Utils import com.starry.greenstash.utils.getActivity import com.starry.greenstash.utils.toToast @@ -130,9 +129,7 @@ fun SettingsScreen(navController: NavController) { LazyColumn(modifier = Modifier.padding(it)) { /** Display Settings */ item { - val themeValue = when (PreferenceUtils.getInt( - PreferenceUtils.APP_THEME, ThemeMode.Auto.ordinal - )) { + val themeValue = when (viewModel.getThemeValue()) { ThemeMode.Light.ordinal -> "Light" ThemeMode.Dark.ordinal -> "Dark" else -> "System" @@ -144,12 +141,7 @@ fun SettingsScreen(navController: NavController) { } val materialYouSwitch = remember { - mutableStateOf( - PreferenceUtils.getBoolean( - PreferenceUtils.MATERIAL_YOU, - Build.VERSION.SDK_INT >= Build.VERSION_CODES.S - ) - ) + mutableStateOf(viewModel.getMaterialYouValue()) } Column( @@ -174,14 +166,12 @@ fun SettingsScreen(navController: NavController) { if (newValue) { if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.S) { viewModel.setMaterialYou(true) - PreferenceUtils.putBoolean(PreferenceUtils.MATERIAL_YOU, true) } else { materialYouSwitch.value = false context.getString(R.string.material_you_error).toToast(context) } } else { viewModel.setMaterialYou(false) - PreferenceUtils.putBoolean(PreferenceUtils.MATERIAL_YOU, false) } } ) @@ -235,30 +225,15 @@ fun SettingsScreen(navController: NavController) { when (selectedThemeOption) { "Light" -> { - viewModel.setTheme( - ThemeMode.Light - ) - PreferenceUtils.putInt( - PreferenceUtils.APP_THEME, ThemeMode.Light.ordinal - ) + viewModel.setTheme(ThemeMode.Light) } "Dark" -> { - viewModel.setTheme( - ThemeMode.Dark - ) - PreferenceUtils.putInt( - PreferenceUtils.APP_THEME, ThemeMode.Dark.ordinal - ) + viewModel.setTheme(ThemeMode.Dark) } "System" -> { - viewModel.setTheme( - ThemeMode.Auto - ) - PreferenceUtils.putInt( - PreferenceUtils.APP_THEME, ThemeMode.Auto.ordinal - ) + viewModel.setTheme(ThemeMode.Auto) } } }) { @@ -278,9 +253,7 @@ fun SettingsScreen(navController: NavController) { /** Locales Setting */ item { - val dateValue = if (PreferenceUtils.getString( - PreferenceUtils.DATE_FORMAT, DateStyle.DateMonthYear.pattern - ) == DateStyle.YearMonthDate.pattern + val dateValue = if (viewModel.getDateStyleValue() == DateStyle.YearMonthDate.pattern ) { "YYYY/MM/DD" } else { @@ -296,11 +269,9 @@ fun SettingsScreen(navController: NavController) { val currencyEntries = context.resources.getStringArray(R.array.currency_entries) val currencyValues = context.resources.getStringArray(R.array.currency_values) - val currencyValue = currencyEntries[currencyValues.indexOf( - PreferenceUtils.getString( - PreferenceUtils.DEFAULT_CURRENCY, currencyValues.first() - ) - )] + val currencyValue = currencyEntries[ + currencyValues.indexOf(viewModel.getDefaultCurrencyValue()) + ] val currencyDialog = remember { mutableStateOf(false) } val (selectedCurrencyOption, onCurrencyOptionSelected) = remember { @@ -371,17 +342,11 @@ fun SettingsScreen(navController: NavController) { when (selectedDateOption) { "DD/MM/YYYY" -> { - PreferenceUtils.putString( - PreferenceUtils.DATE_FORMAT, - DateStyle.DateMonthYear.pattern - ) + viewModel.setDateStyle(DateStyle.DateMonthYear.pattern) } "YYYY/MM/DD" -> { - PreferenceUtils.putString( - PreferenceUtils.DATE_FORMAT, - DateStyle.YearMonthDate.pattern - ) + viewModel.setDateStyle(DateStyle.YearMonthDate.pattern) } } }) { @@ -448,7 +413,7 @@ fun SettingsScreen(navController: NavController) { currencyDialog.value = false val choice = currencyValues[currencyEntries.indexOf(selectedCurrencyOption)] - PreferenceUtils.putString(PreferenceUtils.DEFAULT_CURRENCY, choice) + viewModel.setDefaultCurrency(choice) }) { Text(stringResource(id = R.string.dialog_confirm_button)) } @@ -465,13 +430,7 @@ fun SettingsScreen(navController: NavController) { /** Security Settings. */ item { - val appLockSwitch = remember { - mutableStateOf( - PreferenceUtils.getBoolean( - PreferenceUtils.APP_LOCK, false - ) - ) - } + val appLockSwitch = remember { mutableStateOf(viewModel.getAppLockValue()) } Column( modifier = Modifier.padding(top = 10.dp) @@ -507,10 +466,7 @@ fun SettingsScreen(navController: NavController) { context.getString(R.string.auth_successful) .toToast(context) mainActivity.mainViewModel.appUnlocked = true - PreferenceUtils.putBoolean( - PreferenceUtils.APP_LOCK, - true - ) + viewModel.setAppLock(true) } override fun onAuthenticationFailed() { @@ -528,7 +484,7 @@ fun SettingsScreen(navController: NavController) { biometricPrompt.authenticate(promptInfo) } else { - PreferenceUtils.putBoolean(PreferenceUtils.APP_LOCK, false) + viewModel.setAppLock(false) } } ) diff --git a/app/src/main/java/com/starry/greenstash/ui/screens/settings/viewmodels/SettingsViewModel.kt b/app/src/main/java/com/starry/greenstash/ui/screens/settings/viewmodels/SettingsViewModel.kt index 2a467fff..798ef352 100644 --- a/app/src/main/java/com/starry/greenstash/ui/screens/settings/viewmodels/SettingsViewModel.kt +++ b/app/src/main/java/com/starry/greenstash/ui/screens/settings/viewmodels/SettingsViewModel.kt @@ -31,18 +31,24 @@ import androidx.compose.runtime.Composable import androidx.lifecycle.LiveData import androidx.lifecycle.MutableLiveData import androidx.lifecycle.ViewModel -import com.starry.greenstash.utils.PreferenceUtils +import com.starry.greenstash.utils.PreferenceUtil +import dagger.hilt.android.lifecycle.HiltViewModel +import javax.inject.Inject enum class ThemeMode { Light, Dark, Auto } sealed class DateStyle(val pattern: String) { - object DateMonthYear : DateStyle("dd/MM/yyyy") - object YearMonthDate : DateStyle("yyyy/MM/dd") + data object DateMonthYear : DateStyle("dd/MM/yyyy") + data object YearMonthDate : DateStyle("yyyy/MM/dd") } -class SettingsViewModel : ViewModel() { +@HiltViewModel +class SettingsViewModel @Inject constructor( + private val preferenceUtil: PreferenceUtil +) : ViewModel() { + private val _theme = MutableLiveData(ThemeMode.Auto) private val _materialYou = MutableLiveData(Build.VERSION.SDK_INT >= Build.VERSION_CODES.S) @@ -51,29 +57,50 @@ class SettingsViewModel : ViewModel() { fun setTheme(newTheme: ThemeMode) { _theme.postValue(newTheme) + preferenceUtil.putInt(PreferenceUtil.APP_THEME_INT, newTheme.ordinal) } fun setMaterialYou(newValue: Boolean) { _materialYou.postValue(newValue) + preferenceUtil.putBoolean(PreferenceUtil.MATERIAL_YOU_BOOL, newValue) + } + + fun setDateStyle(newValue: String) { + preferenceUtil.putString(PreferenceUtil.DATE_FORMAT_STR, newValue) + } + + fun setDefaultCurrency(newValue: String) { + preferenceUtil.putString(PreferenceUtil.DEFAULT_CURRENCY_STR, newValue) + } + + fun setAppLock(newValue: Boolean) { + preferenceUtil.putBoolean(PreferenceUtil.APP_LOCK_BOOL, newValue) } + fun getThemeValue() = preferenceUtil.getInt( + PreferenceUtil.APP_THEME_INT, ThemeMode.Auto.ordinal + ) + + fun getMaterialYouValue() = preferenceUtil.getBoolean( + PreferenceUtil.MATERIAL_YOU_BOOL, Build.VERSION.SDK_INT >= Build.VERSION_CODES.S + ) + + fun getDateStyleValue() = preferenceUtil.getString( + PreferenceUtil.DATE_FORMAT_STR, DateStyle.DateMonthYear.pattern + ) + + fun getDefaultCurrencyValue() = preferenceUtil.getString( + PreferenceUtil.DEFAULT_CURRENCY_STR, "$" + ) + + fun getAppLockValue() = preferenceUtil.getBoolean( + PreferenceUtil.APP_LOCK_BOOL, false + ) + @Composable fun getCurrentTheme(): ThemeMode { return if (theme.value == ThemeMode.Auto) { if (isSystemInDarkTheme()) ThemeMode.Dark else ThemeMode.Light } else theme.value!! } - - fun setUpAppTheme() { - when (PreferenceUtils.getInt(PreferenceUtils.APP_THEME, ThemeMode.Auto.ordinal)) { - ThemeMode.Auto.ordinal -> setTheme(ThemeMode.Auto) - ThemeMode.Dark.ordinal -> setTheme(ThemeMode.Dark) - ThemeMode.Light.ordinal -> setTheme(ThemeMode.Light) - } - setMaterialYou( - PreferenceUtils.getBoolean( - PreferenceUtils.MATERIAL_YOU, Build.VERSION.SDK_INT >= Build.VERSION_CODES.S - ) - ) - } } \ No newline at end of file diff --git a/app/src/main/java/com/starry/greenstash/ui/screens/welcome/composables/WelcomeScreen.kt b/app/src/main/java/com/starry/greenstash/ui/screens/welcome/composables/WelcomeScreen.kt index d592a650..ddec6dce 100644 --- a/app/src/main/java/com/starry/greenstash/ui/screens/welcome/composables/WelcomeScreen.kt +++ b/app/src/main/java/com/starry/greenstash/ui/screens/welcome/composables/WelcomeScreen.kt @@ -73,7 +73,6 @@ import com.airbnb.lottie.compose.rememberLottieComposition import com.starry.greenstash.R import com.starry.greenstash.ui.navigation.DrawerScreens import com.starry.greenstash.ui.screens.welcome.viewmodels.WelcomeViewModel -import com.starry.greenstash.utils.PreferenceUtils @Composable fun WelcomeScreen(navController: NavController) { @@ -82,12 +81,7 @@ fun WelcomeScreen(navController: NavController) { val currencyEntries = context.resources.getStringArray(R.array.currency_entries) val currencyValues = context.resources.getStringArray(R.array.currency_values) - - val currencyValue = currencyEntries[currencyValues.indexOf( - PreferenceUtils.getString( - PreferenceUtils.DEFAULT_CURRENCY, currencyValues.first() - ) - )] + val currencyValue = currencyEntries[currencyValues.indexOf(viewModel.getDefaultCurrencyValue())] val currencyDialog = remember { mutableStateOf(false) } val (selectedCurrencyOption, onCurrencyOptionSelected) = remember { @@ -222,9 +216,8 @@ fun WelcomeScreen(navController: NavController) { }, confirmButton = { TextButton(onClick = { currencyDialog.value = false - val choice = - currencyValues[currencyEntries.indexOf(selectedCurrencyOption)] - PreferenceUtils.putString(PreferenceUtils.DEFAULT_CURRENCY, choice) + val choice = currencyValues[currencyEntries.indexOf(selectedCurrencyOption)] + viewModel.setDefaultCurrency(choice) }) { Text(stringResource(id = R.string.dialog_confirm_button)) } diff --git a/app/src/main/java/com/starry/greenstash/ui/screens/welcome/viewmodels/WelcomeViewModel.kt b/app/src/main/java/com/starry/greenstash/ui/screens/welcome/viewmodels/WelcomeViewModel.kt index 911e5d87..63399fc8 100644 --- a/app/src/main/java/com/starry/greenstash/ui/screens/welcome/viewmodels/WelcomeViewModel.kt +++ b/app/src/main/java/com/starry/greenstash/ui/screens/welcome/viewmodels/WelcomeViewModel.kt @@ -28,6 +28,7 @@ package com.starry.greenstash.ui.screens.welcome.viewmodels import androidx.lifecycle.ViewModel import androidx.lifecycle.viewModelScope import com.starry.greenstash.other.WelcomeDataStore +import com.starry.greenstash.utils.PreferenceUtil import dagger.hilt.android.lifecycle.HiltViewModel import kotlinx.coroutines.Dispatchers import kotlinx.coroutines.launch @@ -35,7 +36,8 @@ import javax.inject.Inject @HiltViewModel class WelcomeViewModel @Inject constructor( - private val welcomeDataStore: WelcomeDataStore + private val welcomeDataStore: WelcomeDataStore, + private val preferenceUtil: PreferenceUtil ) : ViewModel() { fun saveOnBoardingState(completed: Boolean) { @@ -43,4 +45,12 @@ class WelcomeViewModel @Inject constructor( welcomeDataStore.saveOnBoardingState(completed = completed) } } + + fun setDefaultCurrency(newValue: String) { + preferenceUtil.putString(PreferenceUtil.DEFAULT_CURRENCY_STR, newValue) + } + + fun getDefaultCurrencyValue() = preferenceUtil.getString( + PreferenceUtil.DEFAULT_CURRENCY_STR, "$" + ) } \ No newline at end of file diff --git a/app/src/main/java/com/starry/greenstash/utils/Extensions.kt b/app/src/main/java/com/starry/greenstash/utils/Extensions.kt index 779a86b5..b34878a8 100644 --- a/app/src/main/java/com/starry/greenstash/utils/Extensions.kt +++ b/app/src/main/java/com/starry/greenstash/utils/Extensions.kt @@ -25,8 +25,11 @@ package com.starry.greenstash.utils +import android.Manifest import android.content.Context import android.content.ContextWrapper +import android.content.pm.PackageManager +import android.os.Build import android.widget.Toast import androidx.appcompat.app.AppCompatActivity import androidx.compose.foundation.lazy.LazyListState @@ -36,6 +39,7 @@ import androidx.compose.runtime.getValue import androidx.compose.runtime.mutableIntStateOf import androidx.compose.runtime.remember import androidx.compose.runtime.setValue +import androidx.core.content.ContextCompat import java.io.File import java.io.PrintWriter @@ -45,6 +49,15 @@ fun Context.getActivity(): AppCompatActivity? = when (this) { else -> null } +fun Context.hasNotificationPermission() = + if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.TIRAMISU) { + ContextCompat.checkSelfPermission( + this, Manifest.permission.POST_NOTIFICATIONS + ) == PackageManager.PERMISSION_GRANTED + } else { + true + } + @Composable fun LazyListState.isScrollingUp(): Boolean { var previousIndex by remember(this) { mutableIntStateOf(firstVisibleItemIndex) } diff --git a/app/src/main/java/com/starry/greenstash/utils/GoalTextUtils.kt b/app/src/main/java/com/starry/greenstash/utils/GoalTextUtils.kt index 99fcf90b..0d6fc974 100644 --- a/app/src/main/java/com/starry/greenstash/utils/GoalTextUtils.kt +++ b/app/src/main/java/com/starry/greenstash/utils/GoalTextUtils.kt @@ -35,7 +35,7 @@ import java.time.LocalDateTime import java.time.format.DateTimeFormatter import java.time.temporal.ChronoUnit -object GoalTextUtils { +class GoalTextUtils(private val preferenceUtil: PreferenceUtil) { data class CalculatedDays( val remainingDays: Long, @@ -66,7 +66,7 @@ object GoalTextUtils { context.getString(R.string.progress_greet5) } } - val defCurrency = PreferenceUtils.getString(PreferenceUtils.DEFAULT_CURRENCY, "") + val defCurrency = preferenceUtil.getString(PreferenceUtil.DEFAULT_CURRENCY_STR, "") text += if (progressPercent < 100) { "\n" + context.getString(R.string.currently_saved_incomplete) } else { @@ -84,7 +84,7 @@ object GoalTextUtils { if ((remainingAmount > 0f)) { if (item.goal.deadline.isNotEmpty() && item.goal.deadline.isNotBlank()) { val calculatedDays = calcRemainingDays(item.goal) - val defCurrency = PreferenceUtils.getString(PreferenceUtils.DEFAULT_CURRENCY, "") + val defCurrency = preferenceUtil.getString(PreferenceUtil.DEFAULT_CURRENCY_STR, "") // build description string. var text = context.getString(R.string.goal_days_left) .format(calculatedDays.parsedEndDate, calculatedDays.remainingDays) + "\n" @@ -140,10 +140,25 @@ object GoalTextUtils { } + fun getRemainingDaysText(context: Context, goalItem: GoalWithTransactions): String { + return if (goalItem.getCurrentlySavedAmount() >= goalItem.goal.targetAmount) { + context.getString(R.string.info_card_goal_achieved) + } else { + if (goalItem.goal.deadline.isNotEmpty() && goalItem.goal.deadline.isNotBlank()) { + val calculatedDays = calcRemainingDays(goalItem.goal) + context.getString(R.string.info_card_remaining_days) + .format(calculatedDays.remainingDays) + } else { + context.getString(R.string.info_card_no_deadline_set) + } + } + } + + fun calcRemainingDays(goal: Goal): CalculatedDays { // calculate remaining days between today and endDate (deadline). - val preferredDateFormat = PreferenceUtils.getString( - PreferenceUtils.DATE_FORMAT, DateStyle.DateMonthYear.pattern + val preferredDateFormat = preferenceUtil.getString( + PreferenceUtil.DATE_FORMAT_STR, DateStyle.DateMonthYear.pattern ) val dateFormatter: DateTimeFormatter = DateTimeFormatter.ofPattern(preferredDateFormat) @@ -156,16 +171,17 @@ object GoalTextUtils { val reverseDate: (String) -> String = { goal.deadline.split("/").reversed().joinToString(separator = "/") } - val endDate = if (goal.deadline.split("/") - .first().length == 2 && preferredDateFormat != DateStyle.DateMonthYear.pattern - ) { - reverseDate(goal.deadline) - } else if (goal.deadline.split("/") - .first().length == 4 && preferredDateFormat != DateStyle.YearMonthDate.pattern - ) { - reverseDate(goal.deadline) - } else { - goal.deadline + + val endDate = when { + goal.deadline.split("/").first().length == 2 && + preferredDateFormat != DateStyle.DateMonthYear.pattern -> + reverseDate(goal.deadline) + + goal.deadline.split("/").first().length == 4 && + preferredDateFormat != DateStyle.YearMonthDate.pattern -> + reverseDate(goal.deadline) + + else -> goal.deadline } val startDateValue: LocalDate = LocalDate.parse(startDate, dateFormatter) diff --git a/app/src/main/java/com/starry/greenstash/utils/PreferenceUtils.kt b/app/src/main/java/com/starry/greenstash/utils/PreferenceUtil.kt similarity index 76% rename from app/src/main/java/com/starry/greenstash/utils/PreferenceUtils.kt rename to app/src/main/java/com/starry/greenstash/utils/PreferenceUtil.kt index f065efae..f2e7ec9d 100644 --- a/app/src/main/java/com/starry/greenstash/utils/PreferenceUtils.kt +++ b/app/src/main/java/com/starry/greenstash/utils/PreferenceUtil.kt @@ -29,32 +29,34 @@ import android.content.Context import android.content.SharedPreferences import com.starry.greenstash.ui.screens.settings.viewmodels.DateStyle -object PreferenceUtils { - private lateinit var prefs: SharedPreferences - private const val PREFS_NAME = "myne_settings" +class PreferenceUtil(context: Context) { - // Preference keys - const val APP_THEME = "theme_settings" - const val MATERIAL_YOU = "material_you" - const val DEFAULT_CURRENCY = "default_currency" - const val DATE_FORMAT = "date_format" - const val APP_LOCK = "app_lock" + companion object { + private const val PREFS_NAME = "greenstash_settings" - fun initialize(context: Context) { + // Preference keys + const val APP_THEME_INT = "theme_settings" + const val MATERIAL_YOU_BOOL = "material_you" + const val DEFAULT_CURRENCY_STR = "default_currency" + const val DATE_FORMAT_STR = "date_format" + const val APP_LOCK_BOOL = "app_lock" + } + + private var prefs: SharedPreferences + + init { prefs = context.getSharedPreferences(PREFS_NAME, Context.MODE_PRIVATE) // Pre-populate some preference data with default values - if (!keyExists(DEFAULT_CURRENCY)) { - putString(DEFAULT_CURRENCY, "$") + if (!keyExists(DEFAULT_CURRENCY_STR)) { + putString(DEFAULT_CURRENCY_STR, "$") } - if (!keyExists(DATE_FORMAT)) { - putString(DATE_FORMAT, DateStyle.DateMonthYear.pattern) + if (!keyExists(DATE_FORMAT_STR)) { + putString(DATE_FORMAT_STR, DateStyle.DateMonthYear.pattern) } } private fun keyExists(key: String): Boolean { - if (prefs.contains(key)) - return true - return false + return prefs.contains(key) } fun putString(key: String, value: String) { diff --git a/app/src/main/java/com/starry/greenstash/widget/GoalWidget.kt b/app/src/main/java/com/starry/greenstash/widget/GoalWidget.kt index 74566691..9bc66427 100644 --- a/app/src/main/java/com/starry/greenstash/widget/GoalWidget.kt +++ b/app/src/main/java/com/starry/greenstash/widget/GoalWidget.kt @@ -38,8 +38,6 @@ import android.view.View import android.widget.RemoteViews import com.starry.greenstash.R import com.starry.greenstash.database.core.GoalWithTransactions -import com.starry.greenstash.utils.GoalTextUtils -import com.starry.greenstash.utils.PreferenceUtils import com.starry.greenstash.utils.Utils import dagger.hilt.EntryPoints @@ -103,7 +101,7 @@ class GoalWidget : AppWidgetProvider() { views.setCharSequence(R.id.widgetTitle, "setText", goalItem.goal.title) // Set Widget description. - val defCurrency = PreferenceUtils.getString(PreferenceUtils.DEFAULT_CURRENCY, "") + val defCurrency = viewModel.getDefaultCurrencyValue() val widgetDesc = context.getString(R.string.goal_widget_desc) .format( "$defCurrency${Utils.formatCurrency(goalItem.getCurrentlySavedAmount())} / $defCurrency${ @@ -118,7 +116,7 @@ class GoalWidget : AppWidgetProvider() { val remainingAmount = (goalItem.goal.targetAmount - goalItem.getCurrentlySavedAmount()) if (remainingAmount > 0f) { if (goalItem.goal.deadline.isNotEmpty() && goalItem.goal.deadline.isNotBlank()) { - val calculatedDays = GoalTextUtils.calcRemainingDays(goalItem.goal) + val calculatedDays = viewModel.goalTextUtils.calcRemainingDays(goalItem.goal) if (calculatedDays.remainingDays > 2) { val amountDays = "$defCurrency${ Utils.formatCurrency( @@ -189,9 +187,8 @@ class GoalWidget : AppWidgetProvider() { private fun initialiseVm(context: Context) { if (!this::viewModel.isInitialized) { - viewModel = EntryPoints.get(context.applicationContext, WidgetEntryPoint::class.java) - .getViewModel() - PreferenceUtils.initialize(context) + viewModel = EntryPoints + .get(context.applicationContext, WidgetEntryPoint::class.java).getViewModel() } } diff --git a/app/src/main/java/com/starry/greenstash/widget/WidgetViewModel.kt b/app/src/main/java/com/starry/greenstash/widget/WidgetViewModel.kt index aac2669c..ad43b499 100644 --- a/app/src/main/java/com/starry/greenstash/widget/WidgetViewModel.kt +++ b/app/src/main/java/com/starry/greenstash/widget/WidgetViewModel.kt @@ -30,6 +30,8 @@ import androidx.lifecycle.viewModelScope import com.starry.greenstash.database.core.GoalWithTransactions import com.starry.greenstash.database.goal.GoalDao import com.starry.greenstash.database.widget.WidgetDao +import com.starry.greenstash.utils.GoalTextUtils +import com.starry.greenstash.utils.PreferenceUtil import kotlinx.coroutines.Dispatchers import kotlinx.coroutines.launch import kotlinx.coroutines.withContext @@ -37,9 +39,12 @@ import javax.inject.Inject class WidgetViewModel @Inject constructor( private val widgetDao: WidgetDao, - private val goalDao: GoalDao + private val goalDao: GoalDao, + private val preferenceUtil: PreferenceUtil ) : ViewModel() { + val goalTextUtils = GoalTextUtils(preferenceUtil) + fun getGoalFromWidgetId( appWidgetId: Int, callback: (goalItem: GoalWithTransactions) -> Unit @@ -50,4 +55,8 @@ class WidgetViewModel @Inject constructor( withContext(Dispatchers.Main) { goalItem?.let { callback(it) } } } } + + fun getDefaultCurrencyValue() = preferenceUtil.getString( + PreferenceUtil.DEFAULT_CURRENCY_STR, "$" + ) } \ No newline at end of file diff --git a/app/src/main/java/com/starry/greenstash/widget/configuration/WidgetConfigActivity.kt b/app/src/main/java/com/starry/greenstash/widget/configuration/WidgetConfigActivity.kt index 02ef2889..f7d1c58d 100644 --- a/app/src/main/java/com/starry/greenstash/widget/configuration/WidgetConfigActivity.kt +++ b/app/src/main/java/com/starry/greenstash/widget/configuration/WidgetConfigActivity.kt @@ -93,7 +93,6 @@ import com.starry.greenstash.R import com.starry.greenstash.ui.screens.settings.viewmodels.SettingsViewModel import com.starry.greenstash.ui.screens.settings.viewmodels.ThemeMode import com.starry.greenstash.ui.theme.GreenStashTheme -import com.starry.greenstash.utils.PreferenceUtils import com.starry.greenstash.widget.GoalWidget import dagger.hilt.android.AndroidEntryPoint import kotlinx.coroutines.ExperimentalCoroutinesApi @@ -114,9 +113,11 @@ class WidgetConfigActivity : AppCompatActivity() { override fun onCreate(savedInstanceState: Bundle?) { super.onCreate(savedInstanceState) - PreferenceUtils.initialize(this) settingsViewModel = ViewModelProvider(this)[SettingsViewModel::class.java] - settingsViewModel.setUpAppTheme() + // Setup app theme according to user's settings. + ThemeMode.entries.find { it.ordinal == settingsViewModel.getThemeValue() } + ?.let { settingsViewModel.setTheme(it) } + settingsViewModel.setMaterialYou(settingsViewModel.getMaterialYouValue()) setContent { GreenStashTheme(settingsViewModel = settingsViewModel) { @@ -236,8 +237,7 @@ class WidgetConfigActivity : AppCompatActivity() { .fillMaxSize() .padding(top = 4.dp) ) { - val defCurrency = - PreferenceUtils.getString(PreferenceUtils.DEFAULT_CURRENCY, "") + val defCurrency = settingsViewModel.getDefaultCurrencyValue() items(allGoals.size) { idx -> val item = allGoals[idx] diff --git a/build.gradle b/build.gradle index fa2aed75..16d1daef 100644 --- a/build.gradle +++ b/build.gradle @@ -1,14 +1,16 @@ buildscript { ext { - kotlin_version = '1.9.0' - hilt_version = '2.48' + kotlin_version = '1.9.21' + gradle_version = '8.2.0' + hilt_version = '2.49' + room_version = '2.6.1' } repositories { google() mavenCentral() } dependencies { - classpath 'com.android.tools.build:gradle:8.1.1' + classpath "com.android.tools.build:gradle:$gradle_version" classpath "org.jetbrains.kotlin:kotlin-gradle-plugin:$kotlin_version" classpath "com.google.dagger:hilt-android-gradle-plugin:$hilt_version" // NOTE: Do not place your application dependencies here; they belong @@ -16,10 +18,9 @@ buildscript { } } -// Top-level build file where you can add configuration options common to all sub-projects/modules. plugins { - id 'com.android.application' version '8.1.1' apply false - id 'com.android.library' version '8.1.1' apply false + id 'com.android.application' version "$gradle_version" apply false + id 'com.android.library' version "$gradle_version" apply false id 'org.jetbrains.kotlin.android' version "$kotlin_version" apply false - id 'com.google.devtools.ksp' version '1.9.0-1.0.13' apply false + id 'com.google.devtools.ksp' version '1.9.21-1.0.16' apply false } \ No newline at end of file diff --git a/gradle/wrapper/gradle-wrapper.properties b/gradle/wrapper/gradle-wrapper.properties index 904f6064..bfffcd91 100644 --- a/gradle/wrapper/gradle-wrapper.properties +++ b/gradle/wrapper/gradle-wrapper.properties @@ -1,6 +1,6 @@ #Mon Jan 23 11:16:57 IST 2023 distributionBase=GRADLE_USER_HOME -distributionUrl=https\://services.gradle.org/distributions/gradle-8.1-bin.zip +distributionUrl=https\://services.gradle.org/distributions/gradle-8.2-bin.zip distributionPath=wrapper/dists zipStorePath=wrapper/dists zipStoreBase=GRADLE_USER_HOME