diff --git a/app/build.gradle.kts b/app/build.gradle.kts index 03206337..b90f4ecf 100644 --- a/app/build.gradle.kts +++ b/app/build.gradle.kts @@ -1,49 +1,12 @@ plugins { - alias(libs.plugins.android.application) - alias(libs.plugins.kotlin.android) + id("com.ujizin.android-application") id(libs.plugins.google.services.get().pluginId) id(libs.plugins.google.crashlytics.get().pluginId) } -apply(from = "$rootDir/config-android.gradle") -apply(from = "$rootDir/config-compose.gradle") - -android { - namespace = "com.ujizin.leafy" - defaultConfig { - applicationId = "com.ujizin.leafy" - versionCode = 1 - versionName = "0.1.0" - } - - signingConfigs { - create("release") { - storeFile = file("${rootProject.extra["RELEASE_STORE_FILE"]}") - storePassword = "${rootProject.extra["RELEASE_STORE_PASSWORD"]}" - keyAlias = "${rootProject.extra["RELEASE_KEY_ALIAS"]}" - keyPassword = "${rootProject.extra["RELEASE_KEY_PASSWORD"]}" - } - } - - buildTypes { - getByName("release") { - isMinifyEnabled = false - resValue("string", "app_name", "Leafy") - signingConfig = signingConfigs.getByName("release") - } - - getByName("debug") { - isMinifyEnabled = false - applicationIdSuffix = ".debug" - versionNameSuffix = "-debug" - resValue("string", "app_name", "Leafy Dev") - } - } -} +android { namespace = "com.ujizin.leafy" } dependencies { - implementation(libs.androidx.core.splashscreen) - implementation(projects.features.home) implementation(projects.features.search) implementation(projects.features.alarm) @@ -60,7 +23,4 @@ dependencies { implementation(projects.core.ui) implementation(projects.core.themes) implementation(projects.core.navigation) - - androidTestImplementation(libs.bundles.test) - androidTestImplementation(libs.bundles.androidx.test) } diff --git a/app/src/main/java/com/ujizin/leafy/AppConfiguration.kt b/app/src/main/java/com/ujizin/leafy/AppConfiguration.kt index 6d8127d2..8bbc31dc 100644 --- a/app/src/main/java/com/ujizin/leafy/AppConfiguration.kt +++ b/app/src/main/java/com/ujizin/leafy/AppConfiguration.kt @@ -15,9 +15,7 @@ import com.ujizin.leafy.user.rememberUserState import com.ujizin.leafy.user.setLanguage @Composable -fun AppCompatActivity.AppConfiguration( - content: @Composable Content, -) { +fun AppCompatActivity.AppConfiguration(content: @Composable Content) { val userState by rememberUserState() when (val state: MainUiState = userState) { is MainUiState.Initialized -> { diff --git a/app/src/main/java/com/ujizin/leafy/BackHandler.kt b/app/src/main/java/com/ujizin/leafy/BackHandler.kt index 8d9bf1d1..45dc6581 100644 --- a/app/src/main/java/com/ujizin/leafy/BackHandler.kt +++ b/app/src/main/java/com/ujizin/leafy/BackHandler.kt @@ -9,20 +9,14 @@ import androidx.navigation.NavHostController import kotlinx.coroutines.launch @Composable -fun BackHandler( - navController: NavHostController, - drawerState: DrawerState, - onFinish: () -> Unit, -) { +fun BackHandler(navController: NavHostController, drawerState: DrawerState, onFinish: () -> Unit) { val scope = rememberCoroutineScope() val isDrawerOpen by rememberUpdatedState(drawerState.isOpen) when { - isDrawerOpen -> androidx.activity.compose.BackHandler { - scope.launch { drawerState.close() } - } - else -> androidx.activity.compose.BackHandler { - if (!navController.navigateUp()) onFinish() - } + isDrawerOpen -> + androidx.activity.compose.BackHandler { scope.launch { drawerState.close() } } + else -> + androidx.activity.compose.BackHandler { if (!navController.navigateUp()) onFinish() } } } diff --git a/app/src/main/java/com/ujizin/leafy/LeafyApplication.kt b/app/src/main/java/com/ujizin/leafy/LeafyApplication.kt index e5975013..0019f686 100644 --- a/app/src/main/java/com/ujizin/leafy/LeafyApplication.kt +++ b/app/src/main/java/com/ujizin/leafy/LeafyApplication.kt @@ -8,8 +8,7 @@ import javax.inject.Inject @HiltAndroidApp class LeafyApplication : Application() { - @Inject - lateinit var alarmNotificator: AlarmNotificator + @Inject lateinit var alarmNotificator: AlarmNotificator override fun onCreate() { super.onCreate() diff --git a/app/src/main/java/com/ujizin/leafy/LeafyNavigation.kt b/app/src/main/java/com/ujizin/leafy/LeafyNavigation.kt index 8d4f5ccc..0ac65494 100644 --- a/app/src/main/java/com/ujizin/leafy/LeafyNavigation.kt +++ b/app/src/main/java/com/ujizin/leafy/LeafyNavigation.kt @@ -27,31 +27,19 @@ import com.ujizin.leafy.search.searchGraph import kotlinx.coroutines.launch @Composable -fun LeafyNavigation( - navController: NavHostController, - drawerState: DrawerState, -) { +fun LeafyNavigation(navController: NavHostController, drawerState: DrawerState) { val scope = rememberCoroutineScope() ScaffoldWithDrawer( - modifier = Modifier - .imePadding() - .navigationBarsPadding(), + modifier = Modifier.imePadding().navigationBarsPadding(), drawerState = drawerState, navController = navController, ) { - NavHost( - navController = navController, - startDestination = Destination.Home, - ) { + NavHost(navController = navController, startDestination = Destination.Home) { homeGraph( enterTransition = { navigationEnterTransition(navController) }, - exitTransition = { - navigationExitTransition(navController).orNone - }, + exitTransition = { navigationExitTransition(navController).orNone }, onTakePictureClick = { navController.navigate(Destination.Camera) }, - onSearchClick = { - navController.navigate(Destination.Search(true)) - }, + onSearchClick = { navController.navigate(Destination.Search(true)) }, onDrawerClick = { scope.launch { drawerState.open() } }, onPlantClick = { plantId -> navController.navigate(Destination.PlantDetails(plantId)) diff --git a/app/src/main/java/com/ujizin/leafy/MainActivity.kt b/app/src/main/java/com/ujizin/leafy/MainActivity.kt index 20e7e998..6e293279 100644 --- a/app/src/main/java/com/ujizin/leafy/MainActivity.kt +++ b/app/src/main/java/com/ujizin/leafy/MainActivity.kt @@ -32,10 +32,7 @@ class MainActivity : AppCompatActivity() { onFinish = ::finish, ) - LeafyNavigation( - navController = navController, - drawerState = drawerState, - ) + LeafyNavigation(navController = navController, drawerState = drawerState) } } } diff --git a/app/src/main/java/com/ujizin/leafy/MainViewModel.kt b/app/src/main/java/com/ujizin/leafy/MainViewModel.kt index 8a580238..aae8db28 100644 --- a/app/src/main/java/com/ujizin/leafy/MainViewModel.kt +++ b/app/src/main/java/com/ujizin/leafy/MainViewModel.kt @@ -5,17 +5,15 @@ import com.ujizin.leafy.domain.model.User import com.ujizin.leafy.domain.result.Result import com.ujizin.leafy.domain.usecase.user.load.LoadUserUseCase import dagger.hilt.android.lifecycle.HiltViewModel +import javax.inject.Inject import kotlinx.coroutines.flow.Flow import kotlinx.coroutines.flow.map -import javax.inject.Inject @HiltViewModel -class MainViewModel @Inject constructor( - private val loadUser: LoadUserUseCase, -) : ViewModel() { +class MainViewModel @Inject constructor(private val loadUser: LoadUserUseCase) : ViewModel() { - fun load(): Flow = loadUser() - .map { result -> + fun load(): Flow = + loadUser().map { result -> when (result) { is Result.Success -> MainUiState.Initialized(result.data) else -> MainUiState.Loading @@ -25,5 +23,6 @@ class MainViewModel @Inject constructor( sealed interface MainUiState { data object Loading : MainUiState + data class Initialized(val user: User) : MainUiState } diff --git a/app/src/main/java/com/ujizin/leafy/user/LanguageExtensions.kt b/app/src/main/java/com/ujizin/leafy/user/LanguageExtensions.kt index 7964b6c5..91e3e005 100644 --- a/app/src/main/java/com/ujizin/leafy/user/LanguageExtensions.kt +++ b/app/src/main/java/com/ujizin/leafy/user/LanguageExtensions.kt @@ -2,11 +2,10 @@ package com.ujizin.leafy.user import com.ujizin.leafy.domain.model.Language -/** - * Get locale by language. - */ +/** Get locale by language. */ val Language.tag: String - get() = when (this) { - Language.PT -> "pt-BR" - Language.EN -> "en-US" - } + get() = + when (this) { + Language.PT -> "pt-BR" + Language.EN -> "en-US" + } diff --git a/app/src/main/java/com/ujizin/leafy/user/UserExtensions.kt b/app/src/main/java/com/ujizin/leafy/user/UserExtensions.kt index f9d777e3..374334e2 100644 --- a/app/src/main/java/com/ujizin/leafy/user/UserExtensions.kt +++ b/app/src/main/java/com/ujizin/leafy/user/UserExtensions.kt @@ -11,13 +11,9 @@ import java.util.Locale fun AppCompatActivity.setLanguage(language: Language) { if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.TIRAMISU) { - getSystemService(LocaleManager::class.java) - .applicationLocales = LocaleList( - Locale.forLanguageTag(language.tag), - ) + getSystemService(LocaleManager::class.java).applicationLocales = + LocaleList(Locale.forLanguageTag(language.tag)) } else { - AppCompatDelegate.setApplicationLocales( - LocaleListCompat.forLanguageTags(language.tag), - ) + AppCompatDelegate.setApplicationLocales(LocaleListCompat.forLanguageTags(language.tag)) } } diff --git a/app/src/main/java/com/ujizin/leafy/user/UserState.kt b/app/src/main/java/com/ujizin/leafy/user/UserState.kt index 366c7354..00b32d9a 100644 --- a/app/src/main/java/com/ujizin/leafy/user/UserState.kt +++ b/app/src/main/java/com/ujizin/leafy/user/UserState.kt @@ -11,9 +11,9 @@ import com.ujizin.leafy.domain.model.Theme import com.ujizin.leafy.domain.model.User @Composable -fun rememberUserState(viewModel: MainViewModel = hiltViewModel()) = remember(viewModel) { - viewModel.load() -}.collectAsStateWithLifecycle(initialValue = MainUiState.Loading) +fun rememberUserState(viewModel: MainViewModel = hiltViewModel()) = + remember(viewModel) { viewModel.load() } + .collectAsStateWithLifecycle(initialValue = MainUiState.Loading) @Composable fun User.isUserInDarkTheme(): Boolean { diff --git a/build.gradle.kts b/build.gradle.kts index 491246ad..7429ceea 100644 --- a/build.gradle.kts +++ b/build.gradle.kts @@ -10,19 +10,8 @@ buildscript { } plugins { - alias(libs.plugins.android.application) apply false - alias(libs.plugins.android.library) apply false - alias(libs.plugins.kotlin.android) apply false - alias(libs.plugins.hilt) apply false - alias(libs.plugins.ksp) apply false alias(libs.plugins.kotlinx.serialization) alias(libs.plugins.detekt) - alias(libs.plugins.spotless) -} - -subprojects { - apply(plugin = rootProject.libs.plugins.spotless.get().pluginId) - apply(from = "${project.rootDir}/spotless.gradle") } detekt { diff --git a/buildSrc/build.gradle.kts b/buildSrc/build.gradle.kts new file mode 100644 index 00000000..927a5e13 --- /dev/null +++ b/buildSrc/build.gradle.kts @@ -0,0 +1,21 @@ +plugins { + `kotlin-dsl` + `kotlin-dsl-precompiled-script-plugins` +} + +repositories { + mavenCentral() + google() + gradlePluginPortal() +} + +dependencies { + implementation(gradleApi()) + implementation(libs.gradle.plugin) + implementation(libs.kotlin.gradle.plugin) + implementation(libs.gradle.api.plugin) + implementation(libs.kfmt.plugin) + implementation(libs.spotless.plugin.gradle) + implementation(libs.hilt.plugin) + implementation(libs.ksp.plugin) +} diff --git a/buildSrc/settings.gradle.kts b/buildSrc/settings.gradle.kts new file mode 100644 index 00000000..fa8bc749 --- /dev/null +++ b/buildSrc/settings.gradle.kts @@ -0,0 +1,7 @@ +dependencyResolutionManagement { + versionCatalogs { + create("libs") { + from(files("../gradle/libs.versions.toml")) + } + } +} \ No newline at end of file diff --git a/buildSrc/src/main/kotlin/com/ujizin/leafy/plugins/com.ujizin.android-application.gradle.kts b/buildSrc/src/main/kotlin/com/ujizin/leafy/plugins/com.ujizin.android-application.gradle.kts new file mode 100644 index 00000000..b1f2f8b5 --- /dev/null +++ b/buildSrc/src/main/kotlin/com/ujizin/leafy/plugins/com.ujizin.android-application.gradle.kts @@ -0,0 +1,52 @@ +import com.ujizin.leafy.plugins.utils.configAndroid +import com.ujizin.leafy.plugins.utils.configApplication + +plugins { + id("com.android.application") + id("kotlin-android") + id("org.jetbrains.kotlin.android") + id("dagger.hilt.android.plugin") + id("com.google.devtools.ksp") + id("com.ujizin.code-quality") +} + +internal val Project.libs: VersionCatalog + get() = project.extensions.getByType().named("libs") + +apply(from = "$rootDir/config-properties.gradle.kts") + +android { + configApplication(project) + configAndroid() + kotlinOptions { + jvmTarget = "17" + } + hilt { + enableAggregatingTask = true + } + + buildFeatures { + compose = true + } + composeOptions { + kotlinCompilerExtensionVersion = libs.findVersion("compose-compiler").get().requiredVersion + } +} + +dependencies { + implementation(platform(libs.findLibrary("firebase-bom").get())) + implementation(libs.findLibrary("firebase-crashlytics-ktx").get()) + implementation(libs.findLibrary("firebase-analytics-ktx").get()) + + implementation(libs.findLibrary("androidx-core-splashscreen").get()) + implementation(libs.findBundle("androidx").get()) + + implementation(platform(libs.findLibrary("compose-bom").get())) + implementation(libs.findBundle("compose").get()) + implementation(libs.findLibrary("hilt-compose").get()) + + implementation(libs.findLibrary("hilt").get()) + ksp(libs.findLibrary("hilt.compiler").get()) + + testImplementation(libs.findLibrary("mockk").get()) +} diff --git a/buildSrc/src/main/kotlin/com/ujizin/leafy/plugins/com.ujizin.android-compose.gradle.kts b/buildSrc/src/main/kotlin/com/ujizin/leafy/plugins/com.ujizin.android-compose.gradle.kts new file mode 100644 index 00000000..61aa8f84 --- /dev/null +++ b/buildSrc/src/main/kotlin/com/ujizin/leafy/plugins/com.ujizin.android-compose.gradle.kts @@ -0,0 +1,27 @@ +plugins { + id("com.ujizin.android-library") +} + +internal val Project.libs: VersionCatalog + get() = project.extensions.getByType().named("libs") + +android { + buildFeatures { + compose = true + } + + composeOptions { + kotlinCompilerExtensionVersion = libs.findVersion("compose-compiler").get().requiredVersion + } +} + +dependencies { + implementation(platform(libs.findLibrary("compose-bom").get())) + implementation(libs.findBundle("compose").get()) + debugImplementation(libs.findBundle("compose-debug").get()) + androidTestImplementation(libs.findLibrary("compose-android-test").get()) + implementation(libs.findLibrary("hilt-compose").get()) + + implementation(libs.findLibrary("android-material").get()) + implementation(libs.findBundle("androidx").get()) +} diff --git a/buildSrc/src/main/kotlin/com/ujizin/leafy/plugins/com.ujizin.android-feature.gradle.kts b/buildSrc/src/main/kotlin/com/ujizin/leafy/plugins/com.ujizin.android-feature.gradle.kts new file mode 100644 index 00000000..e208523d --- /dev/null +++ b/buildSrc/src/main/kotlin/com/ujizin/leafy/plugins/com.ujizin.android-feature.gradle.kts @@ -0,0 +1,11 @@ +plugins { + id("com.ujizin.android-compose") +} + +dependencies { + implementation(project(":core:navigation")) + implementation(project(":core:ui")) + implementation(project(":core:themes")) + testImplementation(project(":core:test")) + androidTestImplementation(project(":core:test")) +} \ No newline at end of file diff --git a/buildSrc/src/main/kotlin/com/ujizin/leafy/plugins/com.ujizin.android-library.gradle.kts b/buildSrc/src/main/kotlin/com/ujizin/leafy/plugins/com.ujizin.android-library.gradle.kts new file mode 100644 index 00000000..296aaf90 --- /dev/null +++ b/buildSrc/src/main/kotlin/com/ujizin/leafy/plugins/com.ujizin.android-library.gradle.kts @@ -0,0 +1,40 @@ +import com.ujizin.leafy.plugins.utils.configAndroid + +plugins { + id("com.android.library") + id("kotlin-android") + id("org.jetbrains.kotlin.android") + id("dagger.hilt.android.plugin") + id("com.google.devtools.ksp") + id("com.ujizin.code-quality") +} + +internal val Project.libs: VersionCatalog + get() = project.extensions.getByType().named("libs") + +android { + configAndroid() + kotlinOptions { + jvmTarget = "17" + } + hilt { + enableAggregatingTask = true + } +} + +dependencies { + if (project.path != ":domain") { + implementation(project(":domain")) + } + + implementation(platform(libs.findLibrary("firebase-bom").get())) + implementation(libs.findLibrary("firebase-crashlytics-ktx").get()) + implementation(libs.findLibrary("firebase-analytics-ktx").get()) + + + implementation(libs.findLibrary("hilt").get()) + ksp(libs.findLibrary("hilt-compiler").get()) + + testImplementation(libs.findLibrary("junit").get()) + testImplementation(libs.findLibrary("mockk").get()) +} diff --git a/buildSrc/src/main/kotlin/com/ujizin/leafy/plugins/com.ujizin.code-quality.gradle.kts b/buildSrc/src/main/kotlin/com/ujizin/leafy/plugins/com.ujizin.code-quality.gradle.kts new file mode 100644 index 00000000..0f27dafb --- /dev/null +++ b/buildSrc/src/main/kotlin/com/ujizin/leafy/plugins/com.ujizin.code-quality.gradle.kts @@ -0,0 +1,24 @@ +plugins { + id("com.ncorti.ktfmt.gradle") + id("com.diffplug.spotless") +} + +internal val Project.libs: VersionCatalog + get() = project.extensions.getByType().named("libs") + +spotless { + format("misc") { + target("**/*.gradle", "**/*.md", "**/.gitignore") + indentWithSpaces() + trimTrailingWhitespace() + endWithNewline() + } + + kotlin { + target("**/*.kt", "**/*.kts") + ktfmt(libs.findVersion("ktfmt").get().requiredVersion).kotlinlangStyle() + trimTrailingWhitespace() + indentWithSpaces() + endWithNewline() + } +} diff --git a/buildSrc/src/main/kotlin/com/ujizin/leafy/plugins/utils/ConfigExtensions.kt b/buildSrc/src/main/kotlin/com/ujizin/leafy/plugins/utils/ConfigExtensions.kt new file mode 100644 index 00000000..39ddd8ac --- /dev/null +++ b/buildSrc/src/main/kotlin/com/ujizin/leafy/plugins/utils/ConfigExtensions.kt @@ -0,0 +1,58 @@ +package com.ujizin.leafy.plugins.utils + +import com.android.build.api.dsl.CommonExtension +import com.android.build.gradle.internal.dsl.BaseAppModuleExtension +import org.gradle.api.JavaVersion +import org.gradle.api.Project +import org.gradle.kotlin.dsl.extra + +fun BaseAppModuleExtension.configApplication(rootProject: Project) = with(rootProject) { + defaultConfig { + applicationId = "com.ujizin.leafy" + versionCode = 1 + versionName = "0.1.0" + } + + signingConfigs { + create("release") { + storeFile = file("${rootProject.extra["RELEASE_STORE_FILE"]}") + storePassword = "${rootProject.extra["RELEASE_STORE_PASSWORD"]}" + keyAlias = "${rootProject.extra["RELEASE_KEY_ALIAS"]}" + keyPassword = "${rootProject.extra["RELEASE_KEY_PASSWORD"]}" + } + } + + buildTypes { + getByName("release") { + isMinifyEnabled = false + resValue("string", "app_name", "Leafy") + signingConfig = signingConfigs.getByName("release") + } + + getByName("debug") { + isMinifyEnabled = false + applicationIdSuffix = ".debug" + versionNameSuffix = "-debug" + resValue("string", "app_name", "Leafy Dev") + } + } +} + +fun CommonExtension<*, *, *, *, *, *>.configAndroid() { + compileSdk = 34 + defaultConfig { + minSdk = 23 + vectorDrawables { + useSupportLibrary = true + } + } + + compileOptions { + sourceCompatibility = JavaVersion.VERSION_17 + targetCompatibility = JavaVersion.VERSION_17 + } + + testOptions { + unitTests.isReturnDefaultValues = true + } +} diff --git a/config-android.gradle b/config-android.gradle deleted file mode 100644 index e4090c7b..00000000 --- a/config-android.gradle +++ /dev/null @@ -1,41 +0,0 @@ -apply plugin: 'kotlin-android' -apply plugin: 'dagger.hilt.android.plugin' -apply plugin: 'com.google.devtools.ksp' - -android { - compileSdk 34 - defaultConfig { - minSdk 23 - targetSdk 34 - vectorDrawables { - useSupportLibrary true - } - } - - compileOptions { - sourceCompatibility JavaVersion.VERSION_17 - targetCompatibility JavaVersion.VERSION_17 - } - - kotlinOptions { - jvmTarget = '17' - } - - hilt { - enableAggregatingTask true - } -} - -dependencies { - implementation libs.hilt - implementation platform(libs.firebase.bom) - implementation libs.firebase.crashlytics.ktx - implementation libs.firebase.analytics.ktx - - ksp libs.hilt.compiler - - testImplementation libs.junit - testImplementation libs.mockk -} - -apply from: "$rootDir/ktlint.gradle" \ No newline at end of file diff --git a/config-compose.gradle b/config-compose.gradle deleted file mode 100644 index e4195ed6..00000000 --- a/config-compose.gradle +++ /dev/null @@ -1,23 +0,0 @@ -android { - defaultConfig { - testInstrumentationRunner "androidx.test.runner.AndroidJUnitRunner" - } - - buildFeatures { - compose = true - } - - composeOptions { - kotlinCompilerExtensionVersion = libs.versions.compose.compiler.get() - } -} - -dependencies { - implementation platform(libs.compose.bom) - implementation libs.bundles.compose - implementation libs.hilt.compose - implementation libs.android.material - implementation libs.bundles.compose.debug - implementation libs.bundles.androidx - androidTestImplementation libs.compose.android.test -} \ No newline at end of file diff --git a/core/local/build.gradle.kts b/core/local/build.gradle.kts index 6f5b5805..230096c5 100644 --- a/core/local/build.gradle.kts +++ b/core/local/build.gradle.kts @@ -1,23 +1,9 @@ plugins { - alias(libs.plugins.android.library) - alias(libs.plugins.kotlin.android) + id("com.ujizin.android-library") alias(libs.plugins.kotlinx.serialization) - alias(libs.plugins.ksp) } -apply(from = "../../config-android.gradle") - -android { - namespace = "com.ujizin.leafy.data.local" - - defaultConfig { - testInstrumentationRunner = "androidx.test.runner.AndroidJUnitRunner" - } - - testOptions { - unitTests.isReturnDefaultValues = true - } -} +android { namespace = "com.ujizin.leafy.data.local" } dependencies { implementation(libs.bundles.datastore) diff --git a/core/local/src/androidTest/java/com/ujizin/leafy/local/BaseDatabaseTest.kt b/core/local/src/androidTest/java/com/ujizin/leafy/local/BaseDatabaseTest.kt index e965be7c..8b5c6da3 100644 --- a/core/local/src/androidTest/java/com/ujizin/leafy/local/BaseDatabaseTest.kt +++ b/core/local/src/androidTest/java/com/ujizin/leafy/local/BaseDatabaseTest.kt @@ -15,8 +15,7 @@ import org.junit.runner.RunWith @RunWith(AndroidJUnit4ClassRunner::class) abstract class BaseDatabaseTest { - @get:Rule - val mainDispatcherRule = TestDispatcherRule() + @get:Rule val mainDispatcherRule = TestDispatcherRule() protected lateinit var db: Database diff --git a/core/local/src/androidTest/java/com/ujizin/leafy/local/datasource/AlarmLocalDataSourceTest.kt b/core/local/src/androidTest/java/com/ujizin/leafy/local/datasource/AlarmLocalDataSourceTest.kt index dada771c..604fb5e2 100644 --- a/core/local/src/androidTest/java/com/ujizin/leafy/local/datasource/AlarmLocalDataSourceTest.kt +++ b/core/local/src/androidTest/java/com/ujizin/leafy/local/datasource/AlarmLocalDataSourceTest.kt @@ -14,45 +14,30 @@ class AlarmLocalDataSourceTest : BaseDatabaseTest() { private lateinit var alarmDao: AlarmDao - private val fakeAlarm = AlarmEntity( - id = 1, - ringtoneUriString = "alarm", - true, - 1, - -1, - 1, - listOf(), - ) - - private val fakePlant = PlantEntity( - id = 1, - title = "fake-plant", - filePath = ":data//fake/path", - favorite = false, - description = "this is a fake plant", - albumId = null, - ) + private val fakeAlarm = + AlarmEntity(id = 1, ringtoneUriString = "alarm", true, 1, -1, 1, listOf()) + + private val fakePlant = + PlantEntity( + id = 1, + title = "fake-plant", + filePath = ":data//fake/path", + favorite = false, + description = "this is a fake plant", + albumId = null, + ) override fun setUp() { super.setUp() alarmDao = db.alarmDao() - runTest { - db.plantDao().insert(fakePlant) - } + runTest { db.plantDao().insert(fakePlant) } } @Test fun writeAlarmsAndReadInList() = runTest { - val fakeAlarm2 = AlarmEntity( - id = 2, - ringtoneUriString = "alarm-2", - true, - 1, - -1, - 1, - listOf(), - ) + val fakeAlarm2 = + AlarmEntity(id = 2, ringtoneUriString = "alarm-2", true, 1, -1, 1, listOf()) val expectedAlarms = listOf(fakeAlarm, fakeAlarm2) expectedAlarms.forEach { alarmDao.insert(it) } @@ -65,24 +50,10 @@ class AlarmLocalDataSourceTest : BaseDatabaseTest() { fun writeAlarmsAndFindByPlantId() = runTest { db.plantDao().insert(fakePlant.copy(id = 2)) - val fakeAlarm2 = AlarmEntity( - id = 2, - ringtoneUriString = "alarm-2", - true, - 2, - -1, - 1, - listOf(), - ) - val fakeAlarm3 = AlarmEntity( - id = 2, - ringtoneUriString = "alarm-3", - true, - 1, - -1, - 1, - listOf(), - ) + val fakeAlarm2 = + AlarmEntity(id = 2, ringtoneUriString = "alarm-2", true, 2, -1, 1, listOf()) + val fakeAlarm3 = + AlarmEntity(id = 2, ringtoneUriString = "alarm-3", true, 1, -1, 1, listOf()) listOf(fakeAlarm, fakeAlarm2, fakeAlarm3).forEach { alarmDao.insert(it) } diff --git a/core/local/src/androidTest/java/com/ujizin/leafy/local/datasource/PlantLocalDataSourceTest.kt b/core/local/src/androidTest/java/com/ujizin/leafy/local/datasource/PlantLocalDataSourceTest.kt index 8f0c0bb9..6a48ebe2 100644 --- a/core/local/src/androidTest/java/com/ujizin/leafy/local/datasource/PlantLocalDataSourceTest.kt +++ b/core/local/src/androidTest/java/com/ujizin/leafy/local/datasource/PlantLocalDataSourceTest.kt @@ -14,14 +14,15 @@ class PlantLocalDataSourceTest : BaseDatabaseTest() { private lateinit var plantDao: PlantDao - private val fakePlant = PlantEntity( - id = 1, - title = "fake-plant", - filePath = ":data//fake/path", - favorite = false, - description = "this is a fake plant", - albumId = null, - ) + private val fakePlant = + PlantEntity( + id = 1, + title = "fake-plant", + filePath = ":data//fake/path", + favorite = false, + description = "this is a fake plant", + albumId = null, + ) override fun setUp() { super.setUp() diff --git a/core/local/src/main/java/com/ujizin/leafy/core/local/Database.kt b/core/local/src/main/java/com/ujizin/leafy/core/local/Database.kt index 9ec4bbe7..8371e8ce 100644 --- a/core/local/src/main/java/com/ujizin/leafy/core/local/Database.kt +++ b/core/local/src/main/java/com/ujizin/leafy/core/local/Database.kt @@ -11,17 +11,8 @@ import com.ujizin.leafy.core.local.model.AlarmEntity import com.ujizin.leafy.core.local.model.AlbumEntity import com.ujizin.leafy.core.local.model.PlantEntity -/** - * Database class. - * */ -@Database( - entities = [ - AlarmEntity::class, - AlbumEntity::class, - PlantEntity::class, - ], - version = 1, -) +/** Database class. */ +@Database(entities = [AlarmEntity::class, AlbumEntity::class, PlantEntity::class], version = 1) @TypeConverters(Converter::class) abstract class Database : RoomDatabase() { diff --git a/core/local/src/main/java/com/ujizin/leafy/core/local/LocalModule.kt b/core/local/src/main/java/com/ujizin/leafy/core/local/LocalModule.kt index 40d3651a..55b3dcf6 100644 --- a/core/local/src/main/java/com/ujizin/leafy/core/local/LocalModule.kt +++ b/core/local/src/main/java/com/ujizin/leafy/core/local/LocalModule.kt @@ -19,9 +19,7 @@ import dagger.hilt.android.qualifiers.ApplicationContext import dagger.hilt.components.SingletonComponent import javax.inject.Singleton -/** - * Dependency injection of Local Module - * */ +/** Dependency injection of Local Module */ @Module @InstallIn(SingletonComponent::class) object LocalModule { @@ -29,44 +27,32 @@ object LocalModule { @Singleton @Provides fun provideDatabase(@ApplicationContext context: Context): Database = - Room.databaseBuilder( - context, - Database::class.java, - Database.NAME, - ).build() + Room.databaseBuilder(context, Database::class.java, Database.NAME).build() @Singleton @Provides fun provideMemoryDatabase(@ApplicationContext context: Context): MemoryDatabase = - Room.inMemoryDatabaseBuilder( - context, - MemoryDatabase::class.java, - ).build() + Room.inMemoryDatabaseBuilder(context, MemoryDatabase::class.java).build() @Singleton @Provides fun provideLocalPlantDataSource( database: Database, memoryDatabase: MemoryDatabase, - ): PlantDataSource = PlantLocalDataSource( - plantDao = database.plantDao(), - memoryPlantDao = memoryDatabase.plantDao(), - mapper = PlantMapper(), - ) + ): PlantDataSource = + PlantLocalDataSource( + plantDao = database.plantDao(), + memoryPlantDao = memoryDatabase.plantDao(), + mapper = PlantMapper(), + ) @Singleton @Provides - fun provideLocalAlarmDataSource( - database: Database, - ): AlarmDataSource = AlarmLocalDataSource( - alarmDao = database.alarmDao(), - mapper = AlarmMapper(), - ) + fun provideLocalAlarmDataSource(database: Database): AlarmDataSource = + AlarmLocalDataSource(alarmDao = database.alarmDao(), mapper = AlarmMapper()) @Singleton @Provides - fun provideUserDataSource(userDataStore: UserDataStore): UserDataSource = UserLocalDataSource( - userDataStore = userDataStore, - userMapper = UserMapper(), - ) + fun provideUserDataSource(userDataStore: UserDataStore): UserDataSource = + UserLocalDataSource(userDataStore = userDataStore, userMapper = UserMapper()) } diff --git a/core/local/src/main/java/com/ujizin/leafy/core/local/MemoryDatabase.kt b/core/local/src/main/java/com/ujizin/leafy/core/local/MemoryDatabase.kt index 3d8497cb..58cab1c3 100644 --- a/core/local/src/main/java/com/ujizin/leafy/core/local/MemoryDatabase.kt +++ b/core/local/src/main/java/com/ujizin/leafy/core/local/MemoryDatabase.kt @@ -11,17 +11,8 @@ import com.ujizin.leafy.core.local.model.AlarmEntity import com.ujizin.leafy.core.local.model.AlbumEntity import com.ujizin.leafy.core.local.model.PlantEntity -/** - * Memory database - * */ -@Database( - entities = [ - PlantEntity::class, - AlarmEntity::class, - AlbumEntity::class, - ], - version = 1, -) +/** Memory database */ +@Database(entities = [PlantEntity::class, AlarmEntity::class, AlbumEntity::class], version = 1) @TypeConverters(Converter::class) abstract class MemoryDatabase : RoomDatabase() { diff --git a/core/local/src/main/java/com/ujizin/leafy/core/local/converter/Converter.kt b/core/local/src/main/java/com/ujizin/leafy/core/local/converter/Converter.kt index 1e70ef12..58eeed02 100644 --- a/core/local/src/main/java/com/ujizin/leafy/core/local/converter/Converter.kt +++ b/core/local/src/main/java/com/ujizin/leafy/core/local/converter/Converter.kt @@ -5,16 +5,12 @@ import kotlinx.serialization.decodeFromString import kotlinx.serialization.encodeToString import kotlinx.serialization.json.Json -/** - * Database converter. - * */ +/** Database converter. */ internal class Converter { private val json: Json = Json - @TypeConverter - fun listStringToJson(list: List) = json.encodeToString(list) + @TypeConverter fun listStringToJson(list: List) = json.encodeToString(list) - @TypeConverter - fun jsonToListString(value: String): List = json.decodeFromString(value) + @TypeConverter fun jsonToListString(value: String): List = json.decodeFromString(value) } diff --git a/core/local/src/main/java/com/ujizin/leafy/core/local/dao/AlarmDao.kt b/core/local/src/main/java/com/ujizin/leafy/core/local/dao/AlarmDao.kt index dd034533..e4e654f1 100644 --- a/core/local/src/main/java/com/ujizin/leafy/core/local/dao/AlarmDao.kt +++ b/core/local/src/main/java/com/ujizin/leafy/core/local/dao/AlarmDao.kt @@ -8,9 +8,7 @@ import androidx.room.Query import androidx.room.Update import com.ujizin.leafy.core.local.model.AlarmEntity -/** - * [Dao] class to handle with [AlarmEntity]. - * */ +/** [Dao] class to handle with [AlarmEntity]. */ @Dao interface AlarmDao { @@ -18,15 +16,14 @@ interface AlarmDao { * Get all [AlarmEntity]. * * @return list of [AlarmEntity] - * */ - @Query("SELECT * FROM alarm") - suspend fun getAll(): List + */ + @Query("SELECT * FROM alarm") suspend fun getAll(): List /** * Get all [AlarmEntity] by plant id. * * @param plantId the plant's id - * */ + */ @Query("SELECT * FROM alarm WHERE plant_id = :plantId") suspend fun getByPlantId(plantId: Long): List @@ -35,7 +32,7 @@ interface AlarmDao { * * @param plantId plant id to find all [AlarmEntity] * @return list of [AlarmEntity] - * */ + */ @Query("SELECT * FROM alarm WHERE plant_id = :plantId") suspend fun findByPlantId(plantId: Long): List? @@ -43,39 +40,35 @@ interface AlarmDao { * Find alarm by id. * * @param id the alarm's id - * */ - @Query("SELECT * FROM alarm WHERE id = :id") - suspend fun findAlarmById(id: Long): AlarmEntity + */ + @Query("SELECT * FROM alarm WHERE id = :id") suspend fun findAlarmById(id: Long): AlarmEntity /** * Insert a new [AlarmEntity]. * * @param alarm [AlarmEntity] to be added - * */ - @Insert(onConflict = OnConflictStrategy.REPLACE) - suspend fun insert(alarm: AlarmEntity): Long + */ + @Insert(onConflict = OnConflictStrategy.REPLACE) suspend fun insert(alarm: AlarmEntity): Long /** * Update [AlarmEntity] passed on parameter. * * @param alarm [AlarmEntity] to be updated - * */ - @Update - suspend fun update(alarm: AlarmEntity) + */ + @Update suspend fun update(alarm: AlarmEntity) /** * Delete [AlarmEntity] passed on parameter. * * @param alarm [AlarmEntity] to be deleted - * */ - @Delete - suspend fun delete(alarm: AlarmEntity) + */ + @Delete suspend fun delete(alarm: AlarmEntity) /** * Delete [AlarmEntity] by plant id. * * @param plantId the alarms plant's id to be deleted - * */ + */ @Query("DELETE FROM alarm WHERE plant_id = :plantId") suspend fun deleteAlarmByPlantId(plantId: Long) } diff --git a/core/local/src/main/java/com/ujizin/leafy/core/local/dao/AlbumDao.kt b/core/local/src/main/java/com/ujizin/leafy/core/local/dao/AlbumDao.kt index 90df9055..0ceab81c 100644 --- a/core/local/src/main/java/com/ujizin/leafy/core/local/dao/AlbumDao.kt +++ b/core/local/src/main/java/com/ujizin/leafy/core/local/dao/AlbumDao.kt @@ -8,9 +8,7 @@ import androidx.room.Query import androidx.room.Update import com.ujizin.leafy.core.local.model.AlbumEntity -/** - * [Dao] class to handle with [AlbumEntity]. - * */ +/** [Dao] class to handle with [AlbumEntity]. */ @Dao interface AlbumDao { @@ -18,16 +16,15 @@ interface AlbumDao { * Get all [AlbumEntity]. * * @return list of [AlbumEntity] - * */ - @Query("SELECT * FROM album") - suspend fun getAll(): List + */ + @Query("SELECT * FROM album") suspend fun getAll(): List /** * Find a list of [AlbumEntity] by album id * * @param albumId the album's id * @return list of [AlbumEntity] - * */ + */ @Query("SELECT * FROM album where album_id = :albumId") suspend fun findAlbumById(albumId: Long): AlbumEntity? @@ -35,23 +32,20 @@ interface AlbumDao { * Insert a new [AlbumEntity]. * * @param album [AlbumEntity] to be added - * */ - @Insert(onConflict = OnConflictStrategy.REPLACE) - suspend fun insert(vararg album: AlbumEntity) + */ + @Insert(onConflict = OnConflictStrategy.REPLACE) suspend fun insert(vararg album: AlbumEntity) /** * Update [AlbumEntity] passed on parameter. * * @param album [AlbumEntity] to be updated - * */ - @Update - suspend fun update(album: AlbumEntity) + */ + @Update suspend fun update(album: AlbumEntity) /** * Delete [AlbumEntity] passed on parameter. * * @param album [AlbumEntity] to be Deleted - * */ - @Delete - suspend fun delete(album: AlbumEntity) + */ + @Delete suspend fun delete(album: AlbumEntity) } diff --git a/core/local/src/main/java/com/ujizin/leafy/core/local/dao/PlantDao.kt b/core/local/src/main/java/com/ujizin/leafy/core/local/dao/PlantDao.kt index eb472ad1..f06171ed 100644 --- a/core/local/src/main/java/com/ujizin/leafy/core/local/dao/PlantDao.kt +++ b/core/local/src/main/java/com/ujizin/leafy/core/local/dao/PlantDao.kt @@ -8,9 +8,7 @@ import androidx.room.Query import androidx.room.Update import com.ujizin.leafy.core.local.model.PlantEntity -/** - * [Dao] class to handle with [PlantEntity]. - * */ +/** [Dao] class to handle with [PlantEntity]. */ @Dao interface PlantDao { @@ -18,38 +16,36 @@ interface PlantDao { * Get all plant entity. * * @return list of [PlantEntity] - * */ - @Query("SELECT * FROM plant") - suspend fun getAll(): List + */ + @Query("SELECT * FROM plant") suspend fun getAll(): List /** - * Find plant by id. + * Find plant by id. * - * @param id id to be found. - * */ - @Query("SELECT * FROM plant where plant_id=:id") - suspend fun findById(id: Long): PlantEntity? + * @param id id to be found. + */ + @Query("SELECT * FROM plant where plant_id=:id") suspend fun findById(id: Long): PlantEntity? /** * Find all plant entity by album id * * @param albumId the album id linked to [PlantEntity] * @return list of [PlantEntity] - * */ + */ @Query("SELECT * FROM plant WHERE album_id = :albumId") suspend fun findByAlbumId(albumId: Long): List /** - * Find plants by title or description. + * Find plants by title or description. * - * @param sentence sentence to find plants - * */ + * @param sentence sentence to find plants + */ @Query( """SELECT * FROM plant WHERE plant_title LIKE '%' || :sentence || '%' OR plant_description LIKE '%' || :sentence || '%' - """, + """ ) suspend fun findBySentence(sentence: String): List @@ -57,30 +53,23 @@ interface PlantDao { * Insert a new [PlantEntity]. * * @return return the new plant's id - * */ - @Insert(onConflict = OnConflictStrategy.REPLACE) - suspend fun insert(plant: PlantEntity): Long + */ + @Insert(onConflict = OnConflictStrategy.REPLACE) suspend fun insert(plant: PlantEntity): Long - /** - * Insert news [PlantEntity]. - * - * */ - @Insert - suspend fun insertAll(vararg plant: PlantEntity) + /** Insert news [PlantEntity]. */ + @Insert suspend fun insertAll(vararg plant: PlantEntity) /** * Update a [PlantEntity] passed on parameter. * * @param plant [PlantEntity] to be updated - * */ - @Update - suspend fun update(plant: PlantEntity) + */ + @Update suspend fun update(plant: PlantEntity) /** * Delete a [PlantEntity] passed on parameter. * * @param plant [PlantEntity] to be deleted - * */ - @Delete - suspend fun delete(plant: PlantEntity) + */ + @Delete suspend fun delete(plant: PlantEntity) } diff --git a/core/local/src/main/java/com/ujizin/leafy/core/local/dao/PlantMemoryDao.kt b/core/local/src/main/java/com/ujizin/leafy/core/local/dao/PlantMemoryDao.kt index 2f604336..6844f808 100644 --- a/core/local/src/main/java/com/ujizin/leafy/core/local/dao/PlantMemoryDao.kt +++ b/core/local/src/main/java/com/ujizin/leafy/core/local/dao/PlantMemoryDao.kt @@ -7,33 +7,23 @@ import androidx.room.Query import androidx.room.Update import com.ujizin.leafy.core.local.model.PlantEntity -/** - * Dao class to handle with [PlantEntity] in memory. - * */ +/** Dao class to handle with [PlantEntity] in memory. */ @Dao interface PlantMemoryDao { - @Query("SELECT * FROM plant LIMIT 1") - suspend fun getDraftPlant(): PlantEntity? + @Query("SELECT * FROM plant LIMIT 1") suspend fun getDraftPlant(): PlantEntity? - /** - * Get [PlantEntity] by id. - * */ + /** Get [PlantEntity] by id. */ @Query("SELECT * FROM plant where plant_id= :plantId LIMIT 1") suspend fun getById(plantId: Long): PlantEntity? - /** - * Insert a new [PlantEntity]. - * - * */ - @Insert(onConflict = OnConflictStrategy.REPLACE) - suspend fun insert(vararg plant: PlantEntity) + /** Insert a new [PlantEntity]. */ + @Insert(onConflict = OnConflictStrategy.REPLACE) suspend fun insert(vararg plant: PlantEntity) /** * Update a [PlantEntity] passed on parameter. * * @param plant [PlantEntity] to be updated - * */ - @Update - suspend fun update(plant: PlantEntity) + */ + @Update suspend fun update(plant: PlantEntity) } diff --git a/core/local/src/main/java/com/ujizin/leafy/core/local/datasource/AlarmLocalDataSource.kt b/core/local/src/main/java/com/ujizin/leafy/core/local/datasource/AlarmLocalDataSource.kt index 17b8b578..3bca4a08 100644 --- a/core/local/src/main/java/com/ujizin/leafy/core/local/datasource/AlarmLocalDataSource.kt +++ b/core/local/src/main/java/com/ujizin/leafy/core/local/datasource/AlarmLocalDataSource.kt @@ -14,16 +14,13 @@ internal class AlarmLocalDataSource( override suspend fun insertAlarms(alarms: List) { val alarmEntities = alarms.map { mapper.toAlarmEntity(it) } - alarmEntities.forEach { alarmEntity -> - alarmDao.insert(alarmEntity) - } + alarmEntities.forEach { alarmEntity -> alarmDao.insert(alarmEntity) } } override suspend fun getAlarms(): List = alarmDao.getAll().map(mapper::toAlarm) - override suspend fun getAlarmsByPlantId( - plantId: Long, - ) = alarmDao.getByPlantId(plantId).map(mapper::toAlarm) + override suspend fun getAlarmsByPlantId(plantId: Long) = + alarmDao.getByPlantId(plantId).map(mapper::toAlarm) override suspend fun getAlarmById(id: Long) = alarmDao.findAlarmById(id).let(mapper::toAlarm) diff --git a/core/local/src/main/java/com/ujizin/leafy/core/local/datasource/PlantLocalDataSource.kt b/core/local/src/main/java/com/ujizin/leafy/core/local/datasource/PlantLocalDataSource.kt index 0d148e7c..00cb5164 100644 --- a/core/local/src/main/java/com/ujizin/leafy/core/local/datasource/PlantLocalDataSource.kt +++ b/core/local/src/main/java/com/ujizin/leafy/core/local/datasource/PlantLocalDataSource.kt @@ -33,14 +33,15 @@ internal class PlantLocalDataSource( plantDao.delete(mapper.toPlantEntity(plant)) } - override suspend fun updateDraftPlant(plant: Plant) = with(memoryPlantDao) { - val plantEntity = mapper.toPlantEntity(plant) - val hasPlant = getById(plantEntity.id) != null - when { - hasPlant -> update(plantEntity) - else -> insert(plantEntity) + override suspend fun updateDraftPlant(plant: Plant) = + with(memoryPlantDao) { + val plantEntity = mapper.toPlantEntity(plant) + val hasPlant = getById(plantEntity.id) != null + when { + hasPlant -> update(plantEntity) + else -> insert(plantEntity) + } } - } override suspend fun findPlantBySentence(sentence: String): List { return plantDao.findBySentence(sentence).map(mapper::toPlant) diff --git a/core/local/src/main/java/com/ujizin/leafy/core/local/datastore/DataStoreModule.kt b/core/local/src/main/java/com/ujizin/leafy/core/local/datastore/DataStoreModule.kt index 90ab4b4b..3467365c 100644 --- a/core/local/src/main/java/com/ujizin/leafy/core/local/datastore/DataStoreModule.kt +++ b/core/local/src/main/java/com/ujizin/leafy/core/local/datastore/DataStoreModule.kt @@ -7,8 +7,8 @@ import dagger.Provides import dagger.hilt.InstallIn import dagger.hilt.android.qualifiers.ApplicationContext import dagger.hilt.components.SingletonComponent -import kotlinx.serialization.json.Json import javax.inject.Singleton +import kotlinx.serialization.json.Json @Module @InstallIn(SingletonComponent::class) @@ -16,10 +16,6 @@ object DataStoreModule { @Provides @Singleton - fun provideUserDataStore( - @ApplicationContext context: Context, - ): UserDataStore = UserDataStoreImpl( - context = context, - serializer = Json, - ) + fun provideUserDataStore(@ApplicationContext context: Context): UserDataStore = + UserDataStoreImpl(context = context, serializer = Json) } diff --git a/core/local/src/main/java/com/ujizin/leafy/core/local/datastore/UserDataStore.kt b/core/local/src/main/java/com/ujizin/leafy/core/local/datastore/UserDataStore.kt index 4288c40b..01f6be30 100644 --- a/core/local/src/main/java/com/ujizin/leafy/core/local/datastore/UserDataStore.kt +++ b/core/local/src/main/java/com/ujizin/leafy/core/local/datastore/UserDataStore.kt @@ -3,22 +3,20 @@ package com.ujizin.leafy.core.local.datastore import com.ujizin.leafy.core.local.model.UserStore import kotlinx.coroutines.flow.Flow -/** - * Data store to User. - * */ +/** Data store to User. */ interface UserDataStore { /** * Get an user. * * @return an user - * */ + */ fun getUser(): Flow /** * Update an user. * * @param user to be updated - * */ + */ suspend fun updateUser(user: UserStore) } diff --git a/core/local/src/main/java/com/ujizin/leafy/core/local/datastore/implementation/UserDataStoreImpl.kt b/core/local/src/main/java/com/ujizin/leafy/core/local/datastore/implementation/UserDataStoreImpl.kt index 6a24d7ca..1d68e9c9 100644 --- a/core/local/src/main/java/com/ujizin/leafy/core/local/datastore/implementation/UserDataStoreImpl.kt +++ b/core/local/src/main/java/com/ujizin/leafy/core/local/datastore/implementation/UserDataStoreImpl.kt @@ -16,10 +16,7 @@ import kotlinx.serialization.decodeFromString import kotlinx.serialization.encodeToString import kotlinx.serialization.json.Json -internal class UserDataStoreImpl( - context: Context, - private val serializer: Json, -) : UserDataStore { +internal class UserDataStoreImpl(context: Context, private val serializer: Json) : UserDataStore { private val Context.userStore by preferencesDataStore(name = USER_PREFERENCES_NAME) @@ -28,29 +25,35 @@ internal class UserDataStoreImpl( private val userKey = stringPreferencesKey("user_stringify") private suspend fun createUser(user: UserStore) { - userStore.edit { preferences -> - preferences[userKey] = Json.encodeToString(user) - } + userStore.edit { preferences -> preferences[userKey] = Json.encodeToString(user) } } - override fun getUser(): Flow = userStore.data.map { preferences -> - val userStore = preferences[userKey] ?: run { - return@map UserStore.default().also { createUser(it) } - } + override fun getUser(): Flow = + userStore.data.map { preferences -> + val userStore = + preferences[userKey] + ?: run { + return@map UserStore.default().also { createUser(it) } + } - serializer.decodeFromString(userStore) - } + serializer.decodeFromString(userStore) + } override suspend fun updateUser(user: UserStore) { userStore.edit { preferences -> - preferences[userKey] = serializer.encodeToString( - value = getUser().firstOrNull().orDefault().copy( - nickname = user.nickname, - theme = user.theme, - language = user.language, - dynamicColor = user.dynamicColor, - ), - ) + preferences[userKey] = + serializer.encodeToString( + value = + getUser() + .firstOrNull() + .orDefault() + .copy( + nickname = user.nickname, + theme = user.theme, + language = user.language, + dynamicColor = user.dynamicColor, + ) + ) } } diff --git a/core/local/src/main/java/com/ujizin/leafy/core/local/mapper/AlarmMapper.kt b/core/local/src/main/java/com/ujizin/leafy/core/local/mapper/AlarmMapper.kt index 11e9a798..e7121b21 100644 --- a/core/local/src/main/java/com/ujizin/leafy/core/local/mapper/AlarmMapper.kt +++ b/core/local/src/main/java/com/ujizin/leafy/core/local/mapper/AlarmMapper.kt @@ -3,32 +3,32 @@ package com.ujizin.leafy.core.local.mapper import com.ujizin.leafy.core.local.model.AlarmEntity import com.ujizin.leafy.core.repository.model.Alarm -/** - * Mapper between [Alarm] and [AlarmEntity] - * */ +/** Mapper between [Alarm] and [AlarmEntity] */ internal class AlarmMapper { - fun toAlarmEntity(alarm: Alarm) = with(alarm) { - AlarmEntity( - id = id, - ringtoneUriString = ringtoneUriString, - minutes = minutes, - hours = hours, - enabled = enabled, - plantId = plantId, - weekDays = weekDays, - ) - } + fun toAlarmEntity(alarm: Alarm) = + with(alarm) { + AlarmEntity( + id = id, + ringtoneUriString = ringtoneUriString, + minutes = minutes, + hours = hours, + enabled = enabled, + plantId = plantId, + weekDays = weekDays, + ) + } - fun toAlarm(alarm: AlarmEntity) = with(alarm) { - Alarm( - id = id, - plantId = plantId, - ringtoneUriString = ringtoneUriString, - hours = hours, - enabled = enabled, - minutes = minutes, - weekDays = weekDays, - ) - } + fun toAlarm(alarm: AlarmEntity) = + with(alarm) { + Alarm( + id = id, + plantId = plantId, + ringtoneUriString = ringtoneUriString, + hours = hours, + enabled = enabled, + minutes = minutes, + weekDays = weekDays, + ) + } } diff --git a/core/local/src/main/java/com/ujizin/leafy/core/local/mapper/AlbumMapper.kt b/core/local/src/main/java/com/ujizin/leafy/core/local/mapper/AlbumMapper.kt index 18dde2ca..94f4b6c5 100644 --- a/core/local/src/main/java/com/ujizin/leafy/core/local/mapper/AlbumMapper.kt +++ b/core/local/src/main/java/com/ujizin/leafy/core/local/mapper/AlbumMapper.kt @@ -3,16 +3,10 @@ package com.ujizin.leafy.core.local.mapper import com.ujizin.leafy.core.local.model.AlbumEntity import com.ujizin.leafy.core.repository.model.Album -/** - * Mapper between [Album] and [AlbumEntity] - * */ +/** Mapper between [Album] and [AlbumEntity] */ internal class AlbumMapper { - fun toAlbumEntity(album: Album) = with(album) { - AlbumEntity(id, title) - } + fun toAlbumEntity(album: Album) = with(album) { AlbumEntity(id, title) } - fun toAlbum(albumEntity: AlbumEntity) = with(albumEntity) { - Album(id, title) - } + fun toAlbum(albumEntity: AlbumEntity) = with(albumEntity) { Album(id, title) } } diff --git a/core/local/src/main/java/com/ujizin/leafy/core/local/mapper/PlantMapper.kt b/core/local/src/main/java/com/ujizin/leafy/core/local/mapper/PlantMapper.kt index b9e4d6c6..b901a90c 100644 --- a/core/local/src/main/java/com/ujizin/leafy/core/local/mapper/PlantMapper.kt +++ b/core/local/src/main/java/com/ujizin/leafy/core/local/mapper/PlantMapper.kt @@ -3,16 +3,12 @@ package com.ujizin.leafy.core.local.mapper import com.ujizin.leafy.core.local.model.PlantEntity import com.ujizin.leafy.core.repository.model.Plant -/** - * Mapper between [Plant] and [PlantEntity] - * */ +/** Mapper between [Plant] and [PlantEntity] */ internal class PlantMapper { - fun toPlant(plantEntity: PlantEntity) = with(plantEntity) { - Plant(id, title, filePath, description, favorite, albumId) - } + fun toPlant(plantEntity: PlantEntity) = + with(plantEntity) { Plant(id, title, filePath, description, favorite, albumId) } - fun toPlantEntity(plant: Plant) = with(plant) { - PlantEntity(id, title, filePath, description, favorite, albumId) - } + fun toPlantEntity(plant: Plant) = + with(plant) { PlantEntity(id, title, filePath, description, favorite, albumId) } } diff --git a/core/local/src/main/java/com/ujizin/leafy/core/local/mapper/UserMapper.kt b/core/local/src/main/java/com/ujizin/leafy/core/local/mapper/UserMapper.kt index 023a459a..1004dd94 100644 --- a/core/local/src/main/java/com/ujizin/leafy/core/local/mapper/UserMapper.kt +++ b/core/local/src/main/java/com/ujizin/leafy/core/local/mapper/UserMapper.kt @@ -3,15 +3,9 @@ package com.ujizin.leafy.core.local.mapper import com.ujizin.leafy.core.local.model.UserStore import com.ujizin.leafy.core.repository.model.User -/** - * Mapper between repository and local modules. - * */ +/** Mapper between repository and local modules. */ class UserMapper { - fun toData(user: UserStore) = with(user) { - User(nickname, theme, language, dynamicColor) - } + fun toData(user: UserStore) = with(user) { User(nickname, theme, language, dynamicColor) } - fun toLocal(user: User) = with(user) { - UserStore(nickname, theme, language, dynamicColor) - } + fun toLocal(user: User) = with(user) { UserStore(nickname, theme, language, dynamicColor) } } diff --git a/core/local/src/main/java/com/ujizin/leafy/core/local/model/AlarmEntity.kt b/core/local/src/main/java/com/ujizin/leafy/core/local/model/AlarmEntity.kt index 1917f608..a2f102ab 100644 --- a/core/local/src/main/java/com/ujizin/leafy/core/local/model/AlarmEntity.kt +++ b/core/local/src/main/java/com/ujizin/leafy/core/local/model/AlarmEntity.kt @@ -14,32 +14,25 @@ import androidx.room.PrimaryKey * @param hours the alarm's hours * @param minutes the alarm's minutes * @param enabled check if alarm is enabled or not - * */ + */ @Entity( tableName = "alarm", - foreignKeys = [ - ForeignKey( - entity = PlantEntity::class, - parentColumns = ["plant_id"], - childColumns = ["plant_id"], - onDelete = ForeignKey.SET_DEFAULT, - ), - ], + foreignKeys = + [ + ForeignKey( + entity = PlantEntity::class, + parentColumns = ["plant_id"], + childColumns = ["plant_id"], + onDelete = ForeignKey.SET_DEFAULT, + ) + ], ) data class AlarmEntity( - @ColumnInfo(name = "id") - @PrimaryKey(autoGenerate = true) - val id: Long = 0, - @ColumnInfo(name = "ringtone") - val ringtoneUriString: String, - @ColumnInfo(name = "enabled") - val enabled: Boolean, - @ColumnInfo(name = "hours") - val hours: Int, - @ColumnInfo(name = "minutes") - val minutes: Int, - @ColumnInfo(name = "plant_id", index = true) - val plantId: Long, - @ColumnInfo(name = "week_days") - val weekDays: List, + @ColumnInfo(name = "id") @PrimaryKey(autoGenerate = true) val id: Long = 0, + @ColumnInfo(name = "ringtone") val ringtoneUriString: String, + @ColumnInfo(name = "enabled") val enabled: Boolean, + @ColumnInfo(name = "hours") val hours: Int, + @ColumnInfo(name = "minutes") val minutes: Int, + @ColumnInfo(name = "plant_id", index = true) val plantId: Long, + @ColumnInfo(name = "week_days") val weekDays: List, ) diff --git a/core/local/src/main/java/com/ujizin/leafy/core/local/model/AlbumEntity.kt b/core/local/src/main/java/com/ujizin/leafy/core/local/model/AlbumEntity.kt index 46752d6c..7310e70a 100644 --- a/core/local/src/main/java/com/ujizin/leafy/core/local/model/AlbumEntity.kt +++ b/core/local/src/main/java/com/ujizin/leafy/core/local/model/AlbumEntity.kt @@ -12,9 +12,6 @@ import androidx.room.PrimaryKey */ @Entity(tableName = "album") data class AlbumEntity( - @ColumnInfo(name = "album_id") - @PrimaryKey(autoGenerate = true) - val id: Long = 0, - @ColumnInfo(name = "album_title") - val title: String, + @ColumnInfo(name = "album_id") @PrimaryKey(autoGenerate = true) val id: Long = 0, + @ColumnInfo(name = "album_title") val title: String, ) diff --git a/core/local/src/main/java/com/ujizin/leafy/core/local/model/PlantEntity.kt b/core/local/src/main/java/com/ujizin/leafy/core/local/model/PlantEntity.kt index 8e2e81e7..ef7a1b34 100644 --- a/core/local/src/main/java/com/ujizin/leafy/core/local/model/PlantEntity.kt +++ b/core/local/src/main/java/com/ujizin/leafy/core/local/model/PlantEntity.kt @@ -13,30 +13,24 @@ import androidx.room.PrimaryKey * @param filePath file path of the plant * @param description the plant description * @param albumId the album id linked to the plant - * */ + */ @Entity( tableName = "plant", - foreignKeys = [ - ForeignKey( - entity = AlbumEntity::class, - parentColumns = ["album_id"], - childColumns = ["album_id"], - onDelete = ForeignKey.SET_DEFAULT, - ), - ], + foreignKeys = + [ + ForeignKey( + entity = AlbumEntity::class, + parentColumns = ["album_id"], + childColumns = ["album_id"], + onDelete = ForeignKey.SET_DEFAULT, + ) + ], ) data class PlantEntity( - @ColumnInfo(name = "plant_id") - @PrimaryKey(autoGenerate = true) - val id: Long = 0, - @ColumnInfo(name = "plant_title") - val title: String, - @ColumnInfo(name = "plant_file_path") - val filePath: String, - @ColumnInfo(name = "plant_description") - val description: String, - @ColumnInfo(name = "plant_favorite") - val favorite: Boolean, - @ColumnInfo(name = "album_id", index = true) - val albumId: Long? = null, + @ColumnInfo(name = "plant_id") @PrimaryKey(autoGenerate = true) val id: Long = 0, + @ColumnInfo(name = "plant_title") val title: String, + @ColumnInfo(name = "plant_file_path") val filePath: String, + @ColumnInfo(name = "plant_description") val description: String, + @ColumnInfo(name = "plant_favorite") val favorite: Boolean, + @ColumnInfo(name = "album_id", index = true) val albumId: Long? = null, ) diff --git a/core/local/src/main/java/com/ujizin/leafy/core/local/model/UserStore.kt b/core/local/src/main/java/com/ujizin/leafy/core/local/model/UserStore.kt index efc3886b..3670ae6c 100644 --- a/core/local/src/main/java/com/ujizin/leafy/core/local/model/UserStore.kt +++ b/core/local/src/main/java/com/ujizin/leafy/core/local/model/UserStore.kt @@ -14,13 +14,14 @@ data class UserStore( companion object { private const val DEFAULT_NICKNAME = "User" - fun default() = UserStore( - nickname = DEFAULT_NICKNAME, - theme = null, - language = "EN", - dynamicColor = true, - createdAt = " ", - ) + fun default() = + UserStore( + nickname = DEFAULT_NICKNAME, + theme = null, + language = "EN", + dynamicColor = true, + createdAt = " ", + ) } } diff --git a/core/navigation/build.gradle.kts b/core/navigation/build.gradle.kts index cb586e0f..4d94a06e 100644 --- a/core/navigation/build.gradle.kts +++ b/core/navigation/build.gradle.kts @@ -1,15 +1,8 @@ plugins { - alias(libs.plugins.android.library) + id("com.ujizin.android-compose") alias(libs.plugins.kotlinx.serialization) } -apply(from = "$rootDir/config-compose.gradle") -apply(from = "$rootDir/config-android.gradle") +android { namespace = "com.ujizin.leafy.navigation" } -android { - namespace = "com.ujizin.leafy.navigation" -} - -dependencies { - implementation(libs.kotlinx.serialization.json) -} \ No newline at end of file +dependencies { implementation(libs.kotlinx.serialization.json) } diff --git a/core/navigation/src/main/java/com/ujizin/leafy/core/navigation/Destination.kt b/core/navigation/src/main/java/com/ujizin/leafy/core/navigation/Destination.kt index b9913a6b..b660ad72 100644 --- a/core/navigation/src/main/java/com/ujizin/leafy/core/navigation/Destination.kt +++ b/core/navigation/src/main/java/com/ujizin/leafy/core/navigation/Destination.kt @@ -6,29 +6,21 @@ import kotlinx.serialization.Serializable sealed interface Destination { - @Serializable - data object Home : Destination + @Serializable data object Home : Destination - @Serializable - data class Search(val autoFocus: Boolean = false) : Destination + @Serializable data class Search(val autoFocus: Boolean = false) : Destination - @Serializable - data object Camera : Destination + @Serializable data object Camera : Destination - @Serializable - data object Tasks : Destination + @Serializable data object Tasks : Destination - @Serializable - data object Preferences : Destination + @Serializable data object Preferences : Destination - @Serializable - data object Publish : Destination + @Serializable data object Publish : Destination - @Serializable - data object Alarm : Destination + @Serializable data object Alarm : Destination - @Serializable - data object About : Destination + @Serializable data object About : Destination @Serializable data class PlantDetails(val plantId: Long) : Destination { @@ -39,8 +31,7 @@ sealed interface Destination { } } - @Serializable - data class PlantEdit(val plantId: Long) : Destination + @Serializable data class PlantEdit(val plantId: Long) : Destination companion object { const val BASE_PATH = "app://leafy" diff --git a/core/navigation/src/main/java/com/ujizin/leafy/core/navigation/NavigationExtensions.kt b/core/navigation/src/main/java/com/ujizin/leafy/core/navigation/NavigationExtensions.kt index cb4ecc21..79674a59 100644 --- a/core/navigation/src/main/java/com/ujizin/leafy/core/navigation/NavigationExtensions.kt +++ b/core/navigation/src/main/java/com/ujizin/leafy/core/navigation/NavigationExtensions.kt @@ -1,5 +1,6 @@ package com.ujizin.leafy.core.navigation +import androidx.compose.animation.AnimatedContentTransitionScope as TransitionScope import androidx.compose.animation.AnimatedVisibilityScope import androidx.compose.animation.EnterTransition import androidx.compose.animation.ExitTransition @@ -12,7 +13,6 @@ import androidx.navigation.NavDeepLink import androidx.navigation.NavDestination import androidx.navigation.NavGraphBuilder import androidx.navigation.compose.composable -import androidx.compose.animation.AnimatedContentTransitionScope as TransitionScope typealias AnimatedEnterTransition = (TransitionScope.() -> EnterTransition?) @@ -41,6 +41,7 @@ fun NavController.navigateUp(times: Int) { } val NavDestination.qualifiedRoute: String? - get() = route - ?.split("?") // Remove queries parameter - ?.firstOrNull() + get() = + route + ?.split("?") // Remove queries parameter + ?.firstOrNull() diff --git a/core/repository/build.gradle.kts b/core/repository/build.gradle.kts index d5e2692f..2d3ab1b2 100644 --- a/core/repository/build.gradle.kts +++ b/core/repository/build.gradle.kts @@ -1,15 +1,5 @@ -plugins { - alias(libs.plugins.android.library) - alias(libs.plugins.kotlin.android) -} +plugins { id("com.ujizin.android-library") } -apply(from = "../../config-android.gradle") +android { namespace = "com.ujizin.leafy.repository" } -android { - namespace = "com.ujizin.leafy.repository" -} - -dependencies { - implementation(projects.domain) - implementation(libs.coroutines) -} +dependencies { implementation(libs.coroutines) } diff --git a/core/repository/src/main/java/com/ujizin/leafy/core/repository/RepositoryModule.kt b/core/repository/src/main/java/com/ujizin/leafy/core/repository/RepositoryModule.kt index c5d4d739..7cbd2e1e 100644 --- a/core/repository/src/main/java/com/ujizin/leafy/core/repository/RepositoryModule.kt +++ b/core/repository/src/main/java/com/ujizin/leafy/core/repository/RepositoryModule.kt @@ -15,35 +15,21 @@ import dagger.Module import dagger.hilt.InstallIn import dagger.hilt.components.SingletonComponent -/** - * Dependency injection of repository module - * */ +/** Dependency injection of repository module */ @Module @InstallIn(SingletonComponent::class) internal interface RepositoryModule { - @Binds - fun providePlantRepository( - plantRepositoryImpl: PlantRepositoryImpl, - ): PlantRepository + @Binds fun providePlantRepository(plantRepositoryImpl: PlantRepositoryImpl): PlantRepository - @Binds - fun provideAlarmRepository( - alarmRepositoryImpl: AlarmRepositoryImpl, - ): AlarmRepository + @Binds fun provideAlarmRepository(alarmRepositoryImpl: AlarmRepositoryImpl): AlarmRepository - @Binds - fun provideUserRepository( - userRepositoryImpl: UserRepositoryImpl, - ): UserRepository + @Binds fun provideUserRepository(userRepositoryImpl: UserRepositoryImpl): UserRepository - @Binds - fun provideFileRepository( - fileRepositoryImpl: FileRepositoryImpl, - ): FileRepository + @Binds fun provideFileRepository(fileRepositoryImpl: FileRepositoryImpl): FileRepository @Binds fun provideRingtoneRepository( - ringtoneRepositoryImpl: RingtoneRepositoryImpl, + ringtoneRepositoryImpl: RingtoneRepositoryImpl ): RingtoneRepository } diff --git a/core/repository/src/main/java/com/ujizin/leafy/core/repository/datasource/AlarmDataSource.kt b/core/repository/src/main/java/com/ujizin/leafy/core/repository/datasource/AlarmDataSource.kt index fed23e54..127f9d31 100644 --- a/core/repository/src/main/java/com/ujizin/leafy/core/repository/datasource/AlarmDataSource.kt +++ b/core/repository/src/main/java/com/ujizin/leafy/core/repository/datasource/AlarmDataSource.kt @@ -2,63 +2,61 @@ package com.ujizin.leafy.core.repository.datasource import com.ujizin.leafy.core.repository.model.Alarm -/** - * Interface Alarm to data source implementation. - * */ +/** Interface Alarm to data source implementation. */ interface AlarmDataSource { /** * Insert a new [Alarm]. * * @param alarm [Alarm] to be added - * */ + */ suspend fun insertAlarm(alarm: Alarm): Long /** * Insert a new list of [Alarm]. * * @param alarms list of [Alarm] to be added - * */ + */ suspend fun insertAlarms(alarms: List) /** * Get all [Alarm] from data source. * * @return all [Alarm] added - * */ + */ suspend fun getAlarms(): List /** * Get all [Alarm] from data source by plant id. * * @param plantId the plant's id - * */ + */ suspend fun getAlarmsByPlantId(plantId: Long): List /** * Update [Alarm] passed on parameter * * @param alarm [Alarm] to be updated - * */ + */ suspend fun updateAlarm(alarm: Alarm) /** * Delete [Alarm] passed on parameter * * @param alarm [Alarm] to be deleted - * */ + */ suspend fun deleteAlarm(alarm: Alarm) /** * Get alarm by id * * @param id the alarm's id - * */ + */ suspend fun getAlarmById(id: Long): Alarm /** * Delete alarm by plant id. * * @param plantId the alarms plant's id to be deleted - * */ + */ suspend fun deleteAlarmByPlantId(plantId: Long) } diff --git a/core/repository/src/main/java/com/ujizin/leafy/core/repository/datasource/AlbumDataSource.kt b/core/repository/src/main/java/com/ujizin/leafy/core/repository/datasource/AlbumDataSource.kt index 6cdcd0c6..8d2231ae 100644 --- a/core/repository/src/main/java/com/ujizin/leafy/core/repository/datasource/AlbumDataSource.kt +++ b/core/repository/src/main/java/com/ujizin/leafy/core/repository/datasource/AlbumDataSource.kt @@ -2,30 +2,28 @@ package com.ujizin.leafy.core.repository.datasource import com.ujizin.leafy.core.repository.model.Album -/** - * Interface Album to data source implementation. - * */ +/** Interface Album to data source implementation. */ interface AlbumDataSource { /** * Insert a new [Album]. * * @param album [Album] to be added - * */ + */ suspend fun insertAlbum(album: Album) /** * Insert a new list of [Album]. * * @param albums list of [Album] to be added - * */ + */ suspend fun insertAlbums(albums: List) /** * Get all [Album] from data source. * * @return all [Album] added - * */ + */ suspend fun getAlbums(): List /** @@ -33,20 +31,20 @@ interface AlbumDataSource { * * @param albumId id's album * @return [Album] found or null - * */ + */ suspend fun findAlbumById(albumId: Long): Album? /** * Update [Album] passed on parameter * * @param album [Album] to be updated - * */ + */ suspend fun updateAlbum(album: Album) /** * Delete [Album] passed on parameter * * @param album [Album] to be deleted - * */ + */ suspend fun deleteAlbum(album: Album) } diff --git a/core/repository/src/main/java/com/ujizin/leafy/core/repository/datasource/PlantDataSource.kt b/core/repository/src/main/java/com/ujizin/leafy/core/repository/datasource/PlantDataSource.kt index 56be1b8b..0efec1fc 100644 --- a/core/repository/src/main/java/com/ujizin/leafy/core/repository/datasource/PlantDataSource.kt +++ b/core/repository/src/main/java/com/ujizin/leafy/core/repository/datasource/PlantDataSource.kt @@ -2,72 +2,66 @@ package com.ujizin.leafy.core.repository.datasource import com.ujizin.leafy.core.repository.model.Plant -/** - * Interface Plant to data source implementation. - * */ +/** Interface Plant to data source implementation. */ interface PlantDataSource { /** * Inserts a new [Plant]. * * @param plant [Plant] to be added - * * @return return the new plant's id - * */ + */ suspend fun insertPlant(plant: Plant): Long /** * Inserts a new list of [Plant]. * * @param plants list of [Plant] to be added - * */ + */ suspend fun insertPlants(plants: List) /** * Get all [Plant] from data source. * * @return all [Plant] added. - * */ + */ suspend fun getPlants(): List /** * Get plant by id. * * @param id the plant's id. - * */ + */ suspend fun getPlant(id: Long): Plant? /** * Update the [Plant] passed on parameter. * * @param plant [Plant] to be updated - * */ + */ suspend fun updatePlant(plant: Plant) /** * Delete the plant passed on parameter. * * @param plant plant to be deleted - * */ + */ suspend fun deletePlant(plant: Plant) /** * Add or update the draft [Plant] passed on parameter. * * @param plant [Plant] to be added in memory. - * */ + */ suspend fun updateDraftPlant(plant: Plant) - /** - * Get draft [Plant]. - * - * */ + /** Get draft [Plant]. */ suspend fun getDraftPlant(): Plant? /** * Find plant by title or description. * * @param sentence sentence to find plants - * */ + */ suspend fun findPlantBySentence(sentence: String): List } diff --git a/core/repository/src/main/java/com/ujizin/leafy/core/repository/datasource/UserDataSource.kt b/core/repository/src/main/java/com/ujizin/leafy/core/repository/datasource/UserDataSource.kt index f27bf1ae..04eb2479 100644 --- a/core/repository/src/main/java/com/ujizin/leafy/core/repository/datasource/UserDataSource.kt +++ b/core/repository/src/main/java/com/ujizin/leafy/core/repository/datasource/UserDataSource.kt @@ -3,22 +3,20 @@ package com.ujizin.leafy.core.repository.datasource import com.ujizin.leafy.core.repository.model.User import kotlinx.coroutines.flow.Flow -/** - * Interface User to data source implementation. - * */ +/** Interface User to data source implementation. */ interface UserDataSource { /** * Get an [User] from data source. * * @return an user - * */ + */ fun getUser(): Flow /** * Update [User]. * * @param user user to be updated - * */ + */ suspend fun updateUser(user: User) } diff --git a/core/repository/src/main/java/com/ujizin/leafy/core/repository/implementation/AlarmRepositoryImpl.kt b/core/repository/src/main/java/com/ujizin/leafy/core/repository/implementation/AlarmRepositoryImpl.kt index 2fb88f3a..6e065042 100644 --- a/core/repository/src/main/java/com/ujizin/leafy/core/repository/implementation/AlarmRepositoryImpl.kt +++ b/core/repository/src/main/java/com/ujizin/leafy/core/repository/implementation/AlarmRepositoryImpl.kt @@ -5,38 +5,35 @@ import com.ujizin.leafy.core.repository.mapper.AlarmMapper import com.ujizin.leafy.domain.dispatcher.IoDispatcher import com.ujizin.leafy.domain.model.Alarm import com.ujizin.leafy.domain.repository.AlarmRepository +import javax.inject.Inject import kotlinx.coroutines.CoroutineDispatcher import kotlinx.coroutines.flow.flow import kotlinx.coroutines.flow.flowOn -import javax.inject.Inject -internal class AlarmRepositoryImpl @Inject constructor( +internal class AlarmRepositoryImpl +@Inject +constructor( private val dataSource: AlarmDataSource, private val mapper: AlarmMapper, @IoDispatcher val dispatcher: CoroutineDispatcher, ) : AlarmRepository { - override fun insertAlarm(alarm: Alarm) = flow { - emit(dataSource.insertAlarm(mapper.toRepo(alarm))) - }.flowOn(dispatcher) + override fun insertAlarm(alarm: Alarm) = + flow { emit(dataSource.insertAlarm(mapper.toRepo(alarm))) }.flowOn(dispatcher) - override fun getAlarms(plantId: Long) = flow { - emit(dataSource.getAlarmsByPlantId(plantId).map(mapper::toDomain)) - }.flowOn(dispatcher) + override fun getAlarms(plantId: Long) = + flow { emit(dataSource.getAlarmsByPlantId(plantId).map(mapper::toDomain)) } + .flowOn(dispatcher) - override fun getAllAlarms() = flow { - emit(dataSource.getAlarms().map(mapper::toDomain)) - }.flowOn(dispatcher) + override fun getAllAlarms() = + flow { emit(dataSource.getAlarms().map(mapper::toDomain)) }.flowOn(dispatcher) - override fun getAlarmById(id: Long) = flow { - emit(mapper.toDomain(dataSource.getAlarmById(id))) - }.flowOn(dispatcher) + override fun getAlarmById(id: Long) = + flow { emit(mapper.toDomain(dataSource.getAlarmById(id))) }.flowOn(dispatcher) - override fun updateAlarm(alarm: Alarm) = flow { - emit(dataSource.updateAlarm(mapper.toRepo(alarm))) - }.flowOn(dispatcher) + override fun updateAlarm(alarm: Alarm) = + flow { emit(dataSource.updateAlarm(mapper.toRepo(alarm))) }.flowOn(dispatcher) - override fun deleteAlarmByPlantId(plantId: Long) = flow { - emit(dataSource.deleteAlarmByPlantId(plantId)) - }.flowOn(dispatcher) + override fun deleteAlarmByPlantId(plantId: Long) = + flow { emit(dataSource.deleteAlarmByPlantId(plantId)) }.flowOn(dispatcher) } diff --git a/core/repository/src/main/java/com/ujizin/leafy/core/repository/implementation/PlantRepositoryImpl.kt b/core/repository/src/main/java/com/ujizin/leafy/core/repository/implementation/PlantRepositoryImpl.kt index 33a5f70e..e8ce120c 100644 --- a/core/repository/src/main/java/com/ujizin/leafy/core/repository/implementation/PlantRepositoryImpl.kt +++ b/core/repository/src/main/java/com/ujizin/leafy/core/repository/implementation/PlantRepositoryImpl.kt @@ -6,51 +6,46 @@ import com.ujizin.leafy.core.repository.utils.createDraft import com.ujizin.leafy.domain.dispatcher.IoDispatcher import com.ujizin.leafy.domain.model.Plant import com.ujizin.leafy.domain.repository.PlantRepository +import javax.inject.Inject import kotlinx.coroutines.CoroutineDispatcher import kotlinx.coroutines.flow.Flow import kotlinx.coroutines.flow.flow import kotlinx.coroutines.flow.flowOn -import javax.inject.Inject -internal class PlantRepositoryImpl @Inject constructor( +internal class PlantRepositoryImpl +@Inject +constructor( private val dataSource: PlantDataSource, private val mapper: PlantMapper, @IoDispatcher private val dispatcher: CoroutineDispatcher, ) : PlantRepository { - override fun getPlants(): Flow> = flow { - emit(mapper.toDomain(dataSource.getPlants())) - }.flowOn(dispatcher) + override fun getPlants(): Flow> = + flow { emit(mapper.toDomain(dataSource.getPlants())) }.flowOn(dispatcher) - override fun getPlant(id: Long): Flow = flow { - emit(dataSource.getPlant(id)?.let(mapper::toDomain)) - }.flowOn(dispatcher) + override fun getPlant(id: Long): Flow = + flow { emit(dataSource.getPlant(id)?.let(mapper::toDomain)) }.flowOn(dispatcher) - override fun insertPlant(plant: Plant) = flow { - emit(dataSource.insertPlant(mapper.toRepo(plant))) - }.flowOn(dispatcher) + override fun insertPlant(plant: Plant) = + flow { emit(dataSource.insertPlant(mapper.toRepo(plant))) }.flowOn(dispatcher) - override fun insertPlants(plants: List) = flow { - emit(dataSource.insertPlants(mapper.toRepo(plants))) - }.flowOn(dispatcher) + override fun insertPlants(plants: List) = + flow { emit(dataSource.insertPlants(mapper.toRepo(plants))) }.flowOn(dispatcher) - override fun updatePlant(plant: Plant) = flow { - emit(dataSource.updatePlant(mapper.toRepo(plant))) - }.flowOn(dispatcher) + override fun updatePlant(plant: Plant) = + flow { emit(dataSource.updatePlant(mapper.toRepo(plant))) }.flowOn(dispatcher) - override fun deletePlant(plant: Plant) = flow { - emit(dataSource.deletePlant(mapper.toRepo(plant))) - }.flowOn(dispatcher) + override fun deletePlant(plant: Plant) = + flow { emit(dataSource.deletePlant(mapper.toRepo(plant))) }.flowOn(dispatcher) - override fun findPlantBySentence(sentence: String) = flow { - emit(dataSource.findPlantBySentence(sentence).map(mapper::toDomain)) - }.flowOn(dispatcher) + override fun findPlantBySentence(sentence: String) = + flow { emit(dataSource.findPlantBySentence(sentence).map(mapper::toDomain)) } + .flowOn(dispatcher) - override fun getDraftPlant() = flow { - emit(dataSource.getDraftPlant()?.let(mapper::toDomain) ?: createDraft()) - }.flowOn(dispatcher) + override fun getDraftPlant() = + flow { emit(dataSource.getDraftPlant()?.let(mapper::toDomain) ?: createDraft()) } + .flowOn(dispatcher) - override fun updateDraftPlant(plant: Plant) = flow { - emit(dataSource.updateDraftPlant(mapper.toRepo(plant))) - }.flowOn(dispatcher) + override fun updateDraftPlant(plant: Plant) = + flow { emit(dataSource.updateDraftPlant(mapper.toRepo(plant))) }.flowOn(dispatcher) } diff --git a/core/repository/src/main/java/com/ujizin/leafy/core/repository/implementation/RingtoneRepositoryImpl.kt b/core/repository/src/main/java/com/ujizin/leafy/core/repository/implementation/RingtoneRepositoryImpl.kt index abfed5ef..099eeb65 100644 --- a/core/repository/src/main/java/com/ujizin/leafy/core/repository/implementation/RingtoneRepositoryImpl.kt +++ b/core/repository/src/main/java/com/ujizin/leafy/core/repository/implementation/RingtoneRepositoryImpl.kt @@ -6,37 +6,41 @@ import com.ujizin.leafy.domain.dispatcher.IoDispatcher import com.ujizin.leafy.domain.model.Ringtone import com.ujizin.leafy.domain.repository.RingtoneRepository import dagger.hilt.android.qualifiers.ApplicationContext +import javax.inject.Inject import kotlinx.coroutines.CoroutineDispatcher import kotlinx.coroutines.flow.Flow import kotlinx.coroutines.flow.flow import kotlinx.coroutines.flow.flowOn -import javax.inject.Inject -internal class RingtoneRepositoryImpl @Inject constructor( +internal class RingtoneRepositoryImpl +@Inject +constructor( @ApplicationContext private val context: Context, @IoDispatcher private val dispatcher: CoroutineDispatcher, ) : RingtoneRepository { - override fun getRingtones(): Flow> = flow { - val ringtoneManager = RingtoneManager(context) - ringtoneManager.setType(RingtoneManager.TYPE_RINGTONE) + override fun getRingtones(): Flow> = + flow { + val ringtoneManager = RingtoneManager(context) + ringtoneManager.setType(RingtoneManager.TYPE_RINGTONE) - val cursor = ringtoneManager.cursor + val cursor = ringtoneManager.cursor - val ringtoneList = mutableListOf() + val ringtoneList = mutableListOf() - if (cursor != null && cursor.moveToFirst()) { - do { - val title = cursor.getString(RingtoneManager.TITLE_COLUMN_INDEX) - val uri = cursor.getString(RingtoneManager.URI_COLUMN_INDEX) - val id = cursor.getString(RingtoneManager.ID_COLUMN_INDEX) + if (cursor != null && cursor.moveToFirst()) { + do { + val title = cursor.getString(RingtoneManager.TITLE_COLUMN_INDEX) + val uri = cursor.getString(RingtoneManager.URI_COLUMN_INDEX) + val id = cursor.getString(RingtoneManager.ID_COLUMN_INDEX) - ringtoneList.add(Ringtone(id, title, "$uri/$id")) - } while (cursor.moveToNext()) - } + ringtoneList.add(Ringtone(id, title, "$uri/$id")) + } while (cursor.moveToNext()) + } - cursor?.close() + cursor?.close() - emit(ringtoneList) - }.flowOn(dispatcher) + emit(ringtoneList) + } + .flowOn(dispatcher) } diff --git a/core/repository/src/main/java/com/ujizin/leafy/core/repository/implementation/UserRepositoryImpl.kt b/core/repository/src/main/java/com/ujizin/leafy/core/repository/implementation/UserRepositoryImpl.kt index 19b70984..597bf8f6 100644 --- a/core/repository/src/main/java/com/ujizin/leafy/core/repository/implementation/UserRepositoryImpl.kt +++ b/core/repository/src/main/java/com/ujizin/leafy/core/repository/implementation/UserRepositoryImpl.kt @@ -5,24 +5,24 @@ import com.ujizin.leafy.core.repository.mapper.UserMapper import com.ujizin.leafy.domain.dispatcher.IoDispatcher import com.ujizin.leafy.domain.model.User import com.ujizin.leafy.domain.repository.UserRepository +import javax.inject.Inject import kotlinx.coroutines.CoroutineDispatcher import kotlinx.coroutines.flow.Flow import kotlinx.coroutines.flow.flow import kotlinx.coroutines.flow.flowOn import kotlinx.coroutines.flow.map -import javax.inject.Inject -internal class UserRepositoryImpl @Inject constructor( +internal class UserRepositoryImpl +@Inject +constructor( private val dataSource: UserDataSource, private val userMapper: UserMapper, @IoDispatcher private val dispatcher: CoroutineDispatcher, ) : UserRepository { - override fun getUser(): Flow = dataSource.getUser() - .map(userMapper::toDomain) - .flowOn(dispatcher) + override fun getUser(): Flow = + dataSource.getUser().map(userMapper::toDomain).flowOn(dispatcher) - override fun updateUser(user: User): Flow = flow { - emit(dataSource.updateUser(userMapper.toData(user))) - }.flowOn(dispatcher) + override fun updateUser(user: User): Flow = + flow { emit(dataSource.updateUser(userMapper.toData(user))) }.flowOn(dispatcher) } diff --git a/core/repository/src/main/java/com/ujizin/leafy/core/repository/mapper/AlarmMapper.kt b/core/repository/src/main/java/com/ujizin/leafy/core/repository/mapper/AlarmMapper.kt index 80121910..0f512a1e 100644 --- a/core/repository/src/main/java/com/ujizin/leafy/core/repository/mapper/AlarmMapper.kt +++ b/core/repository/src/main/java/com/ujizin/leafy/core/repository/mapper/AlarmMapper.kt @@ -1,35 +1,35 @@ package com.ujizin.leafy.core.repository.mapper +import com.ujizin.leafy.core.repository.model.Alarm as RepoAlarm import com.ujizin.leafy.domain.model.Alarm import com.ujizin.leafy.domain.model.WeekDay -import com.ujizin.leafy.core.repository.model.Alarm as RepoAlarm -/** - * Alarm mapper between domain and data modules. - * */ +/** Alarm mapper between domain and data modules. */ internal class AlarmMapper { - fun toRepo(alarm: Alarm) = with(alarm) { - RepoAlarm( - id = id, - plantId = plantId, - ringtoneUriString = ringtoneUriContent, - hours = hours, - minutes = minutes, - enabled = enabled, - weekDays = weekDays.map(WeekDay::name), - ) - } + fun toRepo(alarm: Alarm) = + with(alarm) { + RepoAlarm( + id = id, + plantId = plantId, + ringtoneUriString = ringtoneUriContent, + hours = hours, + minutes = minutes, + enabled = enabled, + weekDays = weekDays.map(WeekDay::name), + ) + } - fun toDomain(alarm: RepoAlarm) = with(alarm) { - Alarm( - id = id, - plantId = plantId, - ringtoneUriContent = ringtoneUriString, - hours = hours, - minutes = minutes, - enabled = enabled, - weekDays = weekDays.map(WeekDay::valueOf), - ) - } + fun toDomain(alarm: RepoAlarm) = + with(alarm) { + Alarm( + id = id, + plantId = plantId, + ringtoneUriContent = ringtoneUriString, + hours = hours, + minutes = minutes, + enabled = enabled, + weekDays = weekDays.map(WeekDay::valueOf), + ) + } } diff --git a/core/repository/src/main/java/com/ujizin/leafy/core/repository/mapper/MapperModule.kt b/core/repository/src/main/java/com/ujizin/leafy/core/repository/mapper/MapperModule.kt index 483c0818..6522be8f 100644 --- a/core/repository/src/main/java/com/ujizin/leafy/core/repository/mapper/MapperModule.kt +++ b/core/repository/src/main/java/com/ujizin/leafy/core/repository/mapper/MapperModule.kt @@ -10,15 +10,9 @@ import javax.inject.Singleton @InstallIn(SingletonComponent::class) internal object MapperModule { - @Provides - @Singleton - fun providePlantMapper() = PlantMapper() + @Provides @Singleton fun providePlantMapper() = PlantMapper() - @Provides - @Singleton - fun provideAlarmMapper() = AlarmMapper() + @Provides @Singleton fun provideAlarmMapper() = AlarmMapper() - @Provides - @Singleton - fun provideUserMapper() = UserMapper() + @Provides @Singleton fun provideUserMapper() = UserMapper() } diff --git a/core/repository/src/main/java/com/ujizin/leafy/core/repository/mapper/PlantMapper.kt b/core/repository/src/main/java/com/ujizin/leafy/core/repository/mapper/PlantMapper.kt index 52d3d931..53fef570 100644 --- a/core/repository/src/main/java/com/ujizin/leafy/core/repository/mapper/PlantMapper.kt +++ b/core/repository/src/main/java/com/ujizin/leafy/core/repository/mapper/PlantMapper.kt @@ -1,29 +1,18 @@ package com.ujizin.leafy.core.repository.mapper -import com.ujizin.leafy.domain.model.Plant import com.ujizin.leafy.core.repository.model.Plant as DataPlant +import com.ujizin.leafy.domain.model.Plant -/** - * Plant mapper between domain and data modules. - * */ +/** Plant mapper between domain and data modules. */ internal class PlantMapper { fun toDomain(plants: List) = plants.map { toDomain(it) } - fun toDomain(plant: DataPlant) = with(plant) { - Plant( - id, - title, - description, - filePath, - favorite, - albumId, - ) - } + fun toDomain(plant: DataPlant) = + with(plant) { Plant(id, title, description, filePath, favorite, albumId) } fun toRepo(plants: List) = plants.map { toRepo(it) } - fun toRepo(plant: Plant) = with(plant) { - DataPlant(id, title, filePath, description, favorite, albumId) - } + fun toRepo(plant: Plant) = + with(plant) { DataPlant(id, title, filePath, description, favorite, albumId) } } diff --git a/core/repository/src/main/java/com/ujizin/leafy/core/repository/mapper/UserMapper.kt b/core/repository/src/main/java/com/ujizin/leafy/core/repository/mapper/UserMapper.kt index c2b9eea8..5fdaf353 100644 --- a/core/repository/src/main/java/com/ujizin/leafy/core/repository/mapper/UserMapper.kt +++ b/core/repository/src/main/java/com/ujizin/leafy/core/repository/mapper/UserMapper.kt @@ -1,32 +1,33 @@ package com.ujizin.leafy.core.repository.mapper +import com.ujizin.leafy.core.repository.model.User as DataUser import com.ujizin.leafy.domain.model.Language import com.ujizin.leafy.domain.model.Theme import com.ujizin.leafy.domain.model.User -import com.ujizin.leafy.core.repository.model.User as DataUser -/** - * User mapper between domain and data modules. - * */ +/** User mapper between domain and data modules. */ internal class UserMapper { - fun toDomain(user: DataUser): User = with(user) { - User( - nickname = nickname, - settings = User.Settings( - language = language.let(Language::valueOf), - theme = theme?.let(Theme::valueOf) ?: Theme.System, - dynamicColor = dynamicColor, - ), - ) - } + fun toDomain(user: DataUser): User = + with(user) { + User( + nickname = nickname, + settings = + User.Settings( + language = language.let(Language::valueOf), + theme = theme?.let(Theme::valueOf) ?: Theme.System, + dynamicColor = dynamicColor, + ), + ) + } - fun toData(user: User): DataUser = with(user) { - DataUser( - nickname = nickname, - theme = settings.theme.toString(), - language = settings.language.toString(), - dynamicColor = settings.dynamicColor, - ) - } + fun toData(user: User): DataUser = + with(user) { + DataUser( + nickname = nickname, + theme = settings.theme.toString(), + language = settings.language.toString(), + dynamicColor = settings.dynamicColor, + ) + } } diff --git a/core/repository/src/main/java/com/ujizin/leafy/core/repository/model/Alarm.kt b/core/repository/src/main/java/com/ujizin/leafy/core/repository/model/Alarm.kt index 9919d954..7b8ef401 100644 --- a/core/repository/src/main/java/com/ujizin/leafy/core/repository/model/Alarm.kt +++ b/core/repository/src/main/java/com/ujizin/leafy/core/repository/model/Alarm.kt @@ -1,16 +1,16 @@ package com.ujizin.leafy.core.repository.model -/*** - * Contract Alarm Model to PlantDataSource +/** + * Contract Alarm Model to PlantDataSource * - * @param id the alarm id - * @param plantId the plant's id - * @param ringtoneUriString the alarm's ringtone uri - * @param hours alarm's hour - * @param enabled check if alarm is enabled or not - * @param minutes alarm's minutes - * @param weekDays day of the week for alarm - * */ + * @param id the alarm id + * @param plantId the plant's id + * @param ringtoneUriString the alarm's ringtone uri + * @param hours alarm's hour + * @param enabled check if alarm is enabled or not + * @param minutes alarm's minutes + * @param weekDays day of the week for alarm + */ data class Alarm( val id: Long = 0, val plantId: Long, diff --git a/core/repository/src/main/java/com/ujizin/leafy/core/repository/model/Album.kt b/core/repository/src/main/java/com/ujizin/leafy/core/repository/model/Album.kt index 21a3eb8e..ef31c365 100644 --- a/core/repository/src/main/java/com/ujizin/leafy/core/repository/model/Album.kt +++ b/core/repository/src/main/java/com/ujizin/leafy/core/repository/model/Album.kt @@ -1,12 +1,9 @@ package com.ujizin.leafy.core.repository.model -/*** +/** * Contract Album Model to AlbumDataSource * * @param id the album id * @param title the album title - * */ -data class Album( - val id: Long = 0, - val title: String, -) + */ +data class Album(val id: Long = 0, val title: String) diff --git a/core/repository/src/main/java/com/ujizin/leafy/core/repository/model/Plant.kt b/core/repository/src/main/java/com/ujizin/leafy/core/repository/model/Plant.kt index a9920dc0..23db36d9 100644 --- a/core/repository/src/main/java/com/ujizin/leafy/core/repository/model/Plant.kt +++ b/core/repository/src/main/java/com/ujizin/leafy/core/repository/model/Plant.kt @@ -1,6 +1,6 @@ package com.ujizin.leafy.core.repository.model -/*** +/** * Contract Plant Model to PlantDataSource. * * @param id the plant id diff --git a/core/repository/src/main/java/com/ujizin/leafy/core/repository/model/User.kt b/core/repository/src/main/java/com/ujizin/leafy/core/repository/model/User.kt index 45052cef..67f6393c 100644 --- a/core/repository/src/main/java/com/ujizin/leafy/core/repository/model/User.kt +++ b/core/repository/src/main/java/com/ujizin/leafy/core/repository/model/User.kt @@ -6,7 +6,7 @@ package com.ujizin.leafy.core.repository.model * @param nickname nickname from user * @param theme theme used for user * @param language language user for user - * */ + */ data class User( val nickname: String, val theme: String?, diff --git a/core/repository/src/main/java/com/ujizin/leafy/core/repository/utils/PlantUtils.kt b/core/repository/src/main/java/com/ujizin/leafy/core/repository/utils/PlantUtils.kt index f96e7258..816b9fb8 100644 --- a/core/repository/src/main/java/com/ujizin/leafy/core/repository/utils/PlantUtils.kt +++ b/core/repository/src/main/java/com/ujizin/leafy/core/repository/utils/PlantUtils.kt @@ -4,9 +4,10 @@ import com.ujizin.leafy.domain.model.Plant import java.io.File import java.util.UUID -fun createDraft() = Plant( - title = "untitled", - filePath = File.createTempFile(UUID.randomUUID().toString(), ".jpg").path, - description = "no description", - favorite = false, -) +fun createDraft() = + Plant( + title = "untitled", + filePath = File.createTempFile(UUID.randomUUID().toString(), ".jpg").path, + description = "no description", + favorite = false, + ) diff --git a/core/test/build.gradle.kts b/core/test/build.gradle.kts index 158f8b1b..9768ef15 100644 --- a/core/test/build.gradle.kts +++ b/core/test/build.gradle.kts @@ -1,14 +1,8 @@ -plugins { - alias(libs.plugins.android.library) -} - -apply(from = "$rootDir/config-android.gradle") +plugins { id("com.ujizin.android-library") } -android { - namespace = "com.ujizin.leafy.test" -} +android { namespace = "com.ujizin.leafy.test" } dependencies { - implementation(libs.coroutines.test) - implementation(libs.bundles.test) + api(libs.coroutines.test) + api(libs.bundles.test) } diff --git a/core/test/src/main/java/com/ujizin/leafy/core/test/TestDispatcherRule.kt b/core/test/src/main/java/com/ujizin/leafy/core/test/TestDispatcherRule.kt index 4f25d558..517977c6 100644 --- a/core/test/src/main/java/com/ujizin/leafy/core/test/TestDispatcherRule.kt +++ b/core/test/src/main/java/com/ujizin/leafy/core/test/TestDispatcherRule.kt @@ -9,13 +9,10 @@ import kotlinx.coroutines.test.setMain import org.junit.rules.TestWatcher import org.junit.runner.Description -/** - * Watcher dispatcher rule to use on tests - * */ +/** Watcher dispatcher rule to use on tests */ @OptIn(ExperimentalCoroutinesApi::class) -class TestDispatcherRule( - val testDispatcher: TestDispatcher = UnconfinedTestDispatcher(), -) : TestWatcher() { +class TestDispatcherRule(val testDispatcher: TestDispatcher = UnconfinedTestDispatcher()) : + TestWatcher() { override fun starting(description: Description) { super.starting(description) diff --git a/core/themes/build.gradle.kts b/core/themes/build.gradle.kts index cd1b459a..30e17a75 100644 --- a/core/themes/build.gradle.kts +++ b/core/themes/build.gradle.kts @@ -1,10 +1,3 @@ -plugins { - alias(libs.plugins.android.library) - alias(libs.plugins.kotlin.android) -} -android { - namespace = "com.ujizin.leafy.core.themes" -} +plugins { id("com.ujizin.android-compose") } -apply(from = "$rootDir/config-compose.gradle") -apply(from = "$rootDir/config-android.gradle") +android { namespace = "com.ujizin.leafy.core.themes" } diff --git a/core/themes/src/main/java/com/ujizin/leafy/core/themes/LeafyTheme.kt b/core/themes/src/main/java/com/ujizin/leafy/core/themes/LeafyTheme.kt index a1973e54..3ff5c2de 100644 --- a/core/themes/src/main/java/com/ujizin/leafy/core/themes/LeafyTheme.kt +++ b/core/themes/src/main/java/com/ujizin/leafy/core/themes/LeafyTheme.kt @@ -16,37 +16,39 @@ import androidx.compose.ui.platform.LocalView import androidx.core.view.ViewCompat import com.google.android.material.color.DynamicColors -private val darkColorScheme = darkColorScheme( - primary = Color.Green800, - secondary = Color.Black800, - tertiary = Color.Gray900, - surface = Color.Black800, - background = Color.Black900, - onPrimary = Color.Gray100, - onSecondary = Color.Gray100, - onBackground = Color.Gray100, - secondaryContainer = Color.Green800, - onSecondaryContainer = Color.Gray300, - outline = Color.Green800, - surfaceVariant = Color.Black800, - onSurface = Color.Gray100, -) +private val darkColorScheme = + darkColorScheme( + primary = Color.Green800, + secondary = Color.Black800, + tertiary = Color.Gray900, + surface = Color.Black800, + background = Color.Black900, + onPrimary = Color.Gray100, + onSecondary = Color.Gray100, + onBackground = Color.Gray100, + secondaryContainer = Color.Green800, + onSecondaryContainer = Color.Gray300, + outline = Color.Green800, + surfaceVariant = Color.Black800, + onSurface = Color.Gray100, + ) -private val lightColorScheme = lightColorScheme( - primary = Color.Green800, - secondary = Color.Green200, - tertiary = Color.Gray100, - surface = Color.Gray200, - background = Color.Gray100, - onPrimary = Color.Gray100, - onSecondary = Color.Gray800, - outline = Color.Green800, - onBackground = Color.Gray800, - secondaryContainer = Color.Green200, - onSecondaryContainer = Color.Gray800, - surfaceVariant = Color.Gray300, - onSurface = Color.Gray900, -) +private val lightColorScheme = + lightColorScheme( + primary = Color.Green800, + secondary = Color.Green200, + tertiary = Color.Gray100, + surface = Color.Gray200, + background = Color.Gray100, + onPrimary = Color.Gray100, + onSecondary = Color.Gray800, + outline = Color.Green800, + onBackground = Color.Gray800, + secondaryContainer = Color.Green200, + onSecondaryContainer = Color.Gray800, + surfaceVariant = Color.Gray300, + onSurface = Color.Gray900, + ) @Composable fun LeafyTheme( @@ -54,15 +56,16 @@ fun LeafyTheme( dynamicColor: Boolean = false, content: @Composable () -> Unit, ) { - val colorScheme = when { - DynamicColors.isDynamicColorAvailable() && dynamicColor -> { - val context = LocalContext.current - if (darkTheme) dynamicDarkColorScheme(context) else dynamicLightColorScheme(context) - } + val colorScheme = + when { + DynamicColors.isDynamicColorAvailable() && dynamicColor -> { + val context = LocalContext.current + if (darkTheme) dynamicDarkColorScheme(context) else dynamicLightColorScheme(context) + } - darkTheme -> darkColorScheme - else -> lightColorScheme - } + darkTheme -> darkColorScheme + else -> lightColorScheme + } val view = LocalView.current if (!view.isInEditMode) { SideEffect { diff --git a/core/themes/src/main/java/com/ujizin/leafy/core/themes/Type.kt b/core/themes/src/main/java/com/ujizin/leafy/core/themes/Type.kt index 4b2cce6d..4341a80c 100644 --- a/core/themes/src/main/java/com/ujizin/leafy/core/themes/Type.kt +++ b/core/themes/src/main/java/com/ujizin/leafy/core/themes/Type.kt @@ -9,37 +9,43 @@ import androidx.compose.ui.text.font.FontFamily import androidx.compose.ui.text.font.FontWeight import androidx.compose.ui.unit.sp -private val PoppinsFamily = FontFamily( - Font(R.font.poppins_bold, FontWeight.Bold), - Font(R.font.poppins_regular, FontWeight.Normal), -) +private val PoppinsFamily = + FontFamily( + Font(R.font.poppins_bold, FontWeight.Bold), + Font(R.font.poppins_regular, FontWeight.Normal), + ) -internal fun getTypography(color: ColorScheme) = Typography( - titleLarge = TextStyle( - fontFamily = PoppinsFamily, - fontSize = 32.sp, - fontWeight = FontWeight.Bold, - color = color.onBackground, - platformStyle = PlatformTextStyle(includeFontPadding = false), - ), - titleMedium = TextStyle( - fontFamily = PoppinsFamily, - fontSize = 24.sp, - fontWeight = FontWeight.Bold, - color = color.onBackground, - platformStyle = PlatformTextStyle(includeFontPadding = false), - ), - titleSmall = TextStyle( - fontFamily = PoppinsFamily, - fontSize = 16.sp, - color = color.onBackground, - fontWeight = FontWeight.Bold, - platformStyle = PlatformTextStyle(includeFontPadding = false), - ), - bodyMedium = TextStyle( - fontFamily = PoppinsFamily, - fontSize = 16.sp, - color = color.onBackground, - platformStyle = PlatformTextStyle(includeFontPadding = false), - ), -) +internal fun getTypography(color: ColorScheme) = + Typography( + titleLarge = + TextStyle( + fontFamily = PoppinsFamily, + fontSize = 32.sp, + fontWeight = FontWeight.Bold, + color = color.onBackground, + platformStyle = PlatformTextStyle(includeFontPadding = false), + ), + titleMedium = + TextStyle( + fontFamily = PoppinsFamily, + fontSize = 24.sp, + fontWeight = FontWeight.Bold, + color = color.onBackground, + platformStyle = PlatformTextStyle(includeFontPadding = false), + ), + titleSmall = + TextStyle( + fontFamily = PoppinsFamily, + fontSize = 16.sp, + color = color.onBackground, + fontWeight = FontWeight.Bold, + platformStyle = PlatformTextStyle(includeFontPadding = false), + ), + bodyMedium = + TextStyle( + fontFamily = PoppinsFamily, + fontSize = 16.sp, + color = color.onBackground, + platformStyle = PlatformTextStyle(includeFontPadding = false), + ), + ) diff --git a/core/ui/build.gradle.kts b/core/ui/build.gradle.kts index cc0b3a54..62224cf5 100644 --- a/core/ui/build.gradle.kts +++ b/core/ui/build.gradle.kts @@ -1,17 +1,11 @@ -plugins { - alias(libs.plugins.android.library) - alias(libs.plugins.kotlin.android) -} - -apply(from = "$rootDir/config-compose.gradle") -apply(from = "$rootDir/config-android.gradle") +plugins { id("com.ujizin.android-compose") } -android { - namespace = "com.ujizin.leafy.core.components" -} +android { namespace = "com.ujizin.leafy.core.components" } dependencies { implementation(projects.core.themes) + + // TODO remove navigation, domain from core:ui implementation(projects.core.navigation) implementation(projects.domain) diff --git a/core/ui/src/main/java/com/ujizin/leafy/core/ui/annotation/DevicePreviews.kt b/core/ui/src/main/java/com/ujizin/leafy/core/ui/annotation/DevicePreviews.kt index 78f0ee62..8497d31b 100644 --- a/core/ui/src/main/java/com/ujizin/leafy/core/ui/annotation/DevicePreviews.kt +++ b/core/ui/src/main/java/com/ujizin/leafy/core/ui/annotation/DevicePreviews.kt @@ -3,8 +3,8 @@ package com.ujizin.leafy.core.ui.annotation import androidx.compose.ui.tooling.preview.Preview /** - * Multi preview annotation that represents various device sizes. Add this annotation to a composable - * to render various devices. + * Multi preview annotation that represents various device sizes. Add this annotation to a + * composable to render various devices. */ @Preview(name = "phone", device = "spec:shape=Normal,width=360,height=640,unit=dp,dpi=480") @Preview(name = "landscape", device = "spec:shape=Normal,width=640,height=360,unit=dp,dpi=480") diff --git a/core/ui/src/main/java/com/ujizin/leafy/core/ui/annotation/ThemePreviews.kt b/core/ui/src/main/java/com/ujizin/leafy/core/ui/annotation/ThemePreviews.kt index 45dc2014..4071d8b2 100644 --- a/core/ui/src/main/java/com/ujizin/leafy/core/ui/annotation/ThemePreviews.kt +++ b/core/ui/src/main/java/com/ujizin/leafy/core/ui/annotation/ThemePreviews.kt @@ -7,12 +7,6 @@ import androidx.compose.ui.tooling.preview.Preview * Multi preview annotation that represents light and dark themes. Add this annotation to a * composable to render the both themes. */ -@Preview( - uiMode = Configuration.UI_MODE_NIGHT_NO, - name = "Light theme", -) -@Preview( - uiMode = Configuration.UI_MODE_NIGHT_YES, - name = "Dark theme", -) +@Preview(uiMode = Configuration.UI_MODE_NIGHT_NO, name = "Light theme") +@Preview(uiMode = Configuration.UI_MODE_NIGHT_YES, name = "Dark theme") annotation class ThemePreviews diff --git a/core/ui/src/main/java/com/ujizin/leafy/core/ui/components/AppPermission.kt b/core/ui/src/main/java/com/ujizin/leafy/core/ui/components/AppPermission.kt index 90146f3d..8590c3b9 100644 --- a/core/ui/src/main/java/com/ujizin/leafy/core/ui/components/AppPermission.kt +++ b/core/ui/src/main/java/com/ujizin/leafy/core/ui/components/AppPermission.kt @@ -10,13 +10,10 @@ import com.ujizin.leafy.core.ui.extensions.Content @OptIn(ExperimentalPermissionsApi::class) @Composable -fun AppPermission( - content: @Composable Content, -) { +fun AppPermission(content: @Composable Content) { if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.TIRAMISU) { - val permissionState = rememberPermissionState( - permission = android.Manifest.permission.POST_NOTIFICATIONS, - ) + val permissionState = + rememberPermissionState(permission = android.Manifest.permission.POST_NOTIFICATIONS) LaunchedEffect(permissionState.status) { if (permissionState.status is PermissionStatus.Denied) { diff --git a/core/ui/src/main/java/com/ujizin/leafy/core/ui/components/EmptySection.kt b/core/ui/src/main/java/com/ujizin/leafy/core/ui/components/EmptySection.kt index ffb569fe..9a9a4e99 100644 --- a/core/ui/src/main/java/com/ujizin/leafy/core/ui/components/EmptySection.kt +++ b/core/ui/src/main/java/com/ujizin/leafy/core/ui/components/EmptySection.kt @@ -51,18 +51,12 @@ fun EmptySection( maxLines = 3, overflow = TextOverflow.Ellipsis, ) - Button( - text = buttonTitle.capitalize(), - enabled = enabled, - onClick = onClick, - ) + Button(text = buttonTitle.capitalize(), enabled = enabled, onClick = onClick) } } @Preview @Composable fun PreviewEmptySection() { - LeafyTheme { - EmptySection {} - } + LeafyTheme { EmptySection {} } } diff --git a/core/ui/src/main/java/com/ujizin/leafy/core/ui/components/ScaffoldWithDrawer.kt b/core/ui/src/main/java/com/ujizin/leafy/core/ui/components/ScaffoldWithDrawer.kt index 13075e26..e72c0b68 100644 --- a/core/ui/src/main/java/com/ujizin/leafy/core/ui/components/ScaffoldWithDrawer.kt +++ b/core/ui/src/main/java/com/ujizin/leafy/core/ui/components/ScaffoldWithDrawer.kt @@ -5,6 +5,7 @@ import androidx.compose.foundation.layout.BoxScope import androidx.compose.foundation.layout.padding import androidx.compose.material3.DrawerState import androidx.compose.material3.ModalNavigationDrawer +import androidx.compose.material3.Scaffold as MaterialScaffold import androidx.compose.runtime.Composable import androidx.compose.runtime.getValue import androidx.compose.runtime.rememberCoroutineScope @@ -17,7 +18,6 @@ import com.ujizin.leafy.core.ui.components.navigation.currentNavItemAsState import com.ujizin.leafy.core.ui.components.navigation.drawer.DrawerContent import com.ujizin.leafy.core.ui.components.navigation.drawer.DrawerItem import kotlinx.coroutines.launch -import androidx.compose.material3.Scaffold as MaterialScaffold @Composable fun ScaffoldWithDrawer( @@ -42,16 +42,12 @@ fun ScaffoldWithDrawer( scope.launch { drawerState.close() } navController.navigateToItem(drawerItem) }, - onCloseDrawer = { - scope.launch { drawerState.close() } - }, + onCloseDrawer = { scope.launch { drawerState.close() } }, ) }, ) { - MaterialScaffold( - modifier = modifier, - bottomBar = { NavigationBar(navController) }, - ) { innerPadding -> + MaterialScaffold(modifier = modifier, bottomBar = { NavigationBar(navController) }) { + innerPadding -> Box( modifier = Modifier.padding(top = innerPadding.calculateTopPadding()), content = content, diff --git a/core/ui/src/main/java/com/ujizin/leafy/core/ui/components/Section.kt b/core/ui/src/main/java/com/ujizin/leafy/core/ui/components/Section.kt index d73e475c..2651cd4e 100644 --- a/core/ui/src/main/java/com/ujizin/leafy/core/ui/components/Section.kt +++ b/core/ui/src/main/java/com/ujizin/leafy/core/ui/components/Section.kt @@ -21,11 +21,7 @@ import com.ujizin.leafy.core.ui.extensions.Content @Composable fun Section( modifier: Modifier = Modifier, - headerPaddingValues: PaddingValues = PaddingValues( - top = 24.dp, - start = 20.dp, - end = 20.dp, - ), + headerPaddingValues: PaddingValues = PaddingValues(top = 24.dp, start = 20.dp, end = 20.dp), title: String, subTitle: String = "", trailingIcon: @Composable Content? = null, @@ -58,10 +54,11 @@ private fun HeaderSection( subTitle: String, headerAnimation: Animation, ) { - val paddingTop by animateDpAsState( - targetValue = if (trailingIcon != null || leadingIcon != null) 12.dp else 0.dp, - label = "header-padding", - ) + val paddingTop by + animateDpAsState( + targetValue = if (trailingIcon != null || leadingIcon != null) 12.dp else 0.dp, + label = "header-padding", + ) Column(modifier) { Toolbar(trailingIcon = trailingIcon, leadingIcon = leadingIcon) diff --git a/core/ui/src/main/java/com/ujizin/leafy/core/ui/components/Toolbar.kt b/core/ui/src/main/java/com/ujizin/leafy/core/ui/components/Toolbar.kt index df1ea848..8f49fad2 100644 --- a/core/ui/src/main/java/com/ujizin/leafy/core/ui/components/Toolbar.kt +++ b/core/ui/src/main/java/com/ujizin/leafy/core/ui/components/Toolbar.kt @@ -16,10 +16,7 @@ internal fun Toolbar( leadingIcon: @Composable Content?, trailingIcon: @Composable Content?, ) { - Row( - modifier.fillMaxWidth(), - horizontalArrangement = Arrangement.SpaceBetween, - ) { + Row(modifier.fillMaxWidth(), horizontalArrangement = Arrangement.SpaceBetween) { leadingIcon?.invoke() trailingIcon?.invoke() } diff --git a/core/ui/src/main/java/com/ujizin/leafy/core/ui/components/animated/AnimatedButtonIcon.kt b/core/ui/src/main/java/com/ujizin/leafy/core/ui/components/animated/AnimatedButtonIcon.kt index 710620f0..81cf2a67 100644 --- a/core/ui/src/main/java/com/ujizin/leafy/core/ui/components/animated/AnimatedButtonIcon.kt +++ b/core/ui/src/main/java/com/ujizin/leafy/core/ui/components/animated/AnimatedButtonIcon.kt @@ -45,9 +45,7 @@ fun AnimatedButtonIcon( onClick = onClick, ) { androidx.compose.material3.Icon( - modifier = Modifier - .padding(innerPaddingValues) - .size(size.takeOrElse { 32.dp }), + modifier = Modifier.padding(innerPaddingValues).size(size.takeOrElse { 32.dp }), painter = painterResource(icon.idRes), tint = tint ?: MaterialTheme.colorScheme.onBackground, contentDescription = stringResource(icon.descriptionRes), diff --git a/core/ui/src/main/java/com/ujizin/leafy/core/ui/components/animated/AnimatedText.kt b/core/ui/src/main/java/com/ujizin/leafy/core/ui/components/animated/AnimatedText.kt index 77d44ddb..43e58e6d 100644 --- a/core/ui/src/main/java/com/ujizin/leafy/core/ui/components/animated/AnimatedText.kt +++ b/core/ui/src/main/java/com/ujizin/leafy/core/ui/components/animated/AnimatedText.kt @@ -39,7 +39,5 @@ fun AnimatedText( @Preview @Composable private fun PreviewTitle() { - LeafyTheme { - AnimatedText(text = "Hello Lucas") - } + LeafyTheme { AnimatedText(text = "Hello Lucas") } } diff --git a/core/ui/src/main/java/com/ujizin/leafy/core/ui/components/animated/animation/Animate.kt b/core/ui/src/main/java/com/ujizin/leafy/core/ui/components/animated/animation/Animate.kt index f06b4f00..b053a956 100644 --- a/core/ui/src/main/java/com/ujizin/leafy/core/ui/components/animated/animation/Animate.kt +++ b/core/ui/src/main/java/com/ujizin/leafy/core/ui/components/animated/animation/Animate.kt @@ -11,7 +11,11 @@ import androidx.compose.ui.Modifier object Animate { enum class Direction { - None, Start, Top, End, Bottom, + None, + Start, + Top, + End, + Bottom, } @Composable @@ -26,24 +30,25 @@ object Animate { return } val visible = rememberSaveable { mutableStateOf(false) } - val visibleState = remember(visibleTarget) { - MutableTransitionState(visible.value).apply { - targetState = visibleTarget - visible.value = visibleTarget + val visibleState = + remember(visibleTarget) { + MutableTransitionState(visible.value).apply { + targetState = visibleTarget + visible.value = visibleTarget + } } - } AnimatedVisibility( modifier = modifier, visibleState = visibleState, - enter = animation.enterTransition() + fadeInEaseInOut( - animation.durationMillis, - animation.delayMillis, - ), - exit = animation.exitTransition() + fadeOutEaseInOut( - animation.durationMillis, - animation.delayMillis, - ), - ) { content() } + enter = + animation.enterTransition() + + fadeInEaseInOut(animation.durationMillis, animation.delayMillis), + exit = + animation.exitTransition() + + fadeOutEaseInOut(animation.durationMillis, animation.delayMillis), + ) { + content() + } } } diff --git a/core/ui/src/main/java/com/ujizin/leafy/core/ui/components/animated/animation/Animation.kt b/core/ui/src/main/java/com/ujizin/leafy/core/ui/components/animated/animation/Animation.kt index 0da0e4ee..4bc2f44b 100644 --- a/core/ui/src/main/java/com/ujizin/leafy/core/ui/components/animated/animation/Animation.kt +++ b/core/ui/src/main/java/com/ujizin/leafy/core/ui/components/animated/animation/Animation.kt @@ -1,6 +1,7 @@ package com.ujizin.leafy.core.ui.components.animated.animation -data class Animation internal constructor( +data class Animation +internal constructor( val direction: Animate.Direction, val delayMillis: Int = 0, val durationMillis: Int = MEDIUM_DURATION, diff --git a/core/ui/src/main/java/com/ujizin/leafy/core/ui/components/animated/animation/AnimationExtensions.kt b/core/ui/src/main/java/com/ujizin/leafy/core/ui/components/animated/animation/AnimationExtensions.kt index 20a19eea..eb00b3c2 100644 --- a/core/ui/src/main/java/com/ujizin/leafy/core/ui/components/animated/animation/AnimationExtensions.kt +++ b/core/ui/src/main/java/com/ujizin/leafy/core/ui/components/animated/animation/AnimationExtensions.kt @@ -15,15 +15,11 @@ import androidx.compose.ui.unit.IntOffset internal fun Animation.enterTransition(): EnterTransition { val animationSpec = tween(durationMillis, delayMillis, FastOutSlowInEasing) return when (direction) { - Animate.Direction.Start -> slideInHorizontally( - animationSpec = animationSpec, - initialOffsetX = { it / 2 }, - ) + Animate.Direction.Start -> + slideInHorizontally(animationSpec = animationSpec, initialOffsetX = { it / 2 }) - Animate.Direction.Top -> slideInVertically( - animationSpec = animationSpec, - initialOffsetY = { it / 2 }, - ) + Animate.Direction.Top -> + slideInVertically(animationSpec = animationSpec, initialOffsetY = { it / 2 }) Animate.Direction.End -> slideInHorizontally(animationSpec = animationSpec) Animate.Direction.Bottom -> slideInVertically(animationSpec = animationSpec) @@ -34,15 +30,11 @@ internal fun Animation.enterTransition(): EnterTransition { internal fun Animation.exitTransition(): ExitTransition { val animationSpec = tween(durationMillis, delayMillis, FastOutSlowInEasing) return when (direction) { - Animate.Direction.Start -> slideOutHorizontally( - animationSpec = animationSpec, - targetOffsetX = { it * 2 }, - ) + Animate.Direction.Start -> + slideOutHorizontally(animationSpec = animationSpec, targetOffsetX = { it * 2 }) - Animate.Direction.Top -> slideOutVertically( - animationSpec = animationSpec, - targetOffsetY = { it * 2 }, - ) + Animate.Direction.Top -> + slideOutVertically(animationSpec = animationSpec, targetOffsetY = { it * 2 }) Animate.Direction.End -> slideOutHorizontally(animationSpec = animationSpec) Animate.Direction.Bottom -> slideOutVertically(animationSpec = animationSpec) @@ -50,10 +42,8 @@ internal fun Animation.exitTransition(): ExitTransition { } } -internal fun fadeInEaseInOut(durationMillis: Int, delayMillis: Int) = fadeIn( - animationSpec = tween(durationMillis, delayMillis, FastOutSlowInEasing), -) +internal fun fadeInEaseInOut(durationMillis: Int, delayMillis: Int) = + fadeIn(animationSpec = tween(durationMillis, delayMillis, FastOutSlowInEasing)) -internal fun fadeOutEaseInOut(durationMillis: Int, delayMillis: Int) = fadeOut( - animationSpec = tween(durationMillis, delayMillis, FastOutSlowInEasing), -) +internal fun fadeOutEaseInOut(durationMillis: Int, delayMillis: Int) = + fadeOut(animationSpec = tween(durationMillis, delayMillis, FastOutSlowInEasing)) diff --git a/core/ui/src/main/java/com/ujizin/leafy/core/ui/components/button/Button.kt b/core/ui/src/main/java/com/ujizin/leafy/core/ui/components/button/Button.kt index 570eb86c..22ac474b 100644 --- a/core/ui/src/main/java/com/ujizin/leafy/core/ui/components/button/Button.kt +++ b/core/ui/src/main/java/com/ujizin/leafy/core/ui/components/button/Button.kt @@ -2,6 +2,7 @@ package com.ujizin.leafy.core.ui.components.button import androidx.compose.foundation.layout.PaddingValues import androidx.compose.foundation.shape.RoundedCornerShape +import androidx.compose.material3.Button as Material3Button import androidx.compose.material3.MaterialTheme import androidx.compose.runtime.Composable import androidx.compose.runtime.getValue @@ -14,7 +15,6 @@ import com.ujizin.leafy.core.themes.LeafyTheme import com.ujizin.leafy.core.ui.components.animated.AnimatedText import com.ujizin.leafy.core.ui.extensions.Content import com.ujizin.leafy.core.ui.extensions.OnClick -import androidx.compose.material3.Button as Material3Button @Composable fun Button( @@ -35,17 +35,15 @@ fun Button( onClick = onClick, ) { text?.let { text -> - val contentColor by rememberUpdatedState( - newValue = when { - enabled -> MaterialTheme.colorScheme.onPrimary - else -> MaterialTheme.colorScheme.onSurface - }, - ) - AnimatedText( - color = contentColor, - capitalize = capitalize, - text = text, - ) + val contentColor by + rememberUpdatedState( + newValue = + when { + enabled -> MaterialTheme.colorScheme.onPrimary + else -> MaterialTheme.colorScheme.onSurface + } + ) + AnimatedText(color = contentColor, capitalize = capitalize, text = text) } ?: content() } } @@ -53,7 +51,5 @@ fun Button( @Preview @Composable fun PreviewButton() { - LeafyTheme { - Button(text = "Hello world!", onClick = {}) - } + LeafyTheme { Button(text = "Hello world!", onClick = {}) } } diff --git a/core/ui/src/main/java/com/ujizin/leafy/core/ui/components/button/CameraButton.kt b/core/ui/src/main/java/com/ujizin/leafy/core/ui/components/button/CameraButton.kt index 0553ffb2..16fddbb5 100644 --- a/core/ui/src/main/java/com/ujizin/leafy/core/ui/components/button/CameraButton.kt +++ b/core/ui/src/main/java/com/ujizin/leafy/core/ui/components/button/CameraButton.kt @@ -30,21 +30,18 @@ internal fun CameraButton( iconAnimation: Animation = Animation.SlideToTop.copy(delayMillis = Animation.LARGE_DELAY), onClick: OnClick, ) { - Box( - modifier = modifier, - contentAlignment = Alignment.Center, - ) { + Box(modifier = modifier, contentAlignment = Alignment.Center) { Animated(animation = animation) { Box( - modifier = Modifier - .clip(CircleShape) - .size(72.dp) - .background(MaterialTheme.colorScheme.background, CircleShape) - .clickable( - indication = ripple(bounded = true), - onClick = onClick, - interactionSource = remember { MutableInteractionSource() }, - ), + modifier = + Modifier.clip(CircleShape) + .size(72.dp) + .background(MaterialTheme.colorScheme.background, CircleShape) + .clickable( + indication = ripple(bounded = true), + onClick = onClick, + interactionSource = remember { MutableInteractionSource() }, + ), contentAlignment = Alignment.Center, ) { Animated(animation = iconAnimation) { @@ -64,9 +61,6 @@ internal fun CameraButton( @Composable private fun PreviewCameraButton() { LeafyTheme(dynamicColor = false) { - CameraButton( - animation = Animation.None, - iconAnimation = Animation.None, - ) {} + CameraButton(animation = Animation.None, iconAnimation = Animation.None) {} } } diff --git a/core/ui/src/main/java/com/ujizin/leafy/core/ui/components/card/CardImage.kt b/core/ui/src/main/java/com/ujizin/leafy/core/ui/components/card/CardImage.kt index ccda2793..e750dc3c 100644 --- a/core/ui/src/main/java/com/ujizin/leafy/core/ui/components/card/CardImage.kt +++ b/core/ui/src/main/java/com/ujizin/leafy/core/ui/components/card/CardImage.kt @@ -37,22 +37,17 @@ fun CardImage( innerContent: @Composable Content = {}, ) { val context = LocalContext.current - val model = remember(data) { - ImageRequest.Builder(context) - .data(data) - .size(Size.ORIGINAL) - .crossfade(true) - .build() - } + val model = + remember(data) { + ImageRequest.Builder(context).data(data).size(Size.ORIGINAL).crossfade(true).build() + } val painter = rememberAsyncImagePainter(model = model) - val alphaAnimated by animateFloatAsState( - targetValue = if (painter.state is AsyncImagePainter.State.Success) 1F else 0F, - ) - Animated( - modifier = Modifier.alpha(alphaAnimated), - animation = animation, - ) { + val alphaAnimated by + animateFloatAsState( + targetValue = if (painter.state is AsyncImagePainter.State.Success) 1F else 0F + ) + Animated(modifier = Modifier.alpha(alphaAnimated), animation = animation) { Card( modifier = modifier, elevation = CardDefaults.cardElevation(defaultElevation = elevation), @@ -64,7 +59,9 @@ fun CardImage( painter = painter, contentDescription = contentDescription, contentAlignment = Alignment.BottomStart, - ) { innerContent() } + ) { + innerContent() + } } } } diff --git a/core/ui/src/main/java/com/ujizin/leafy/core/ui/components/dropdown/DropdownWarningMenuItem.kt b/core/ui/src/main/java/com/ujizin/leafy/core/ui/components/dropdown/DropdownWarningMenuItem.kt index 2c6d1243..c623b5df 100644 --- a/core/ui/src/main/java/com/ujizin/leafy/core/ui/components/dropdown/DropdownWarningMenuItem.kt +++ b/core/ui/src/main/java/com/ujizin/leafy/core/ui/components/dropdown/DropdownWarningMenuItem.kt @@ -26,14 +26,8 @@ fun WarningContent( onConfirm: () -> Unit, ) { Column(modifier) { - Text( - text = title.capitalize(), - style = MaterialTheme.typography.titleMedium, - ) - Text( - modifier = Modifier.padding(top = 16.dp), - text = text.capitalize(), - ) + Text(text = title.capitalize(), style = MaterialTheme.typography.titleMedium) + Text(modifier = Modifier.padding(top = 16.dp), text = text.capitalize()) Row( modifier = Modifier.padding(top = 24.dp), horizontalArrangement = Arrangement.spacedBy(8.dp), diff --git a/core/ui/src/main/java/com/ujizin/leafy/core/ui/components/header/HeaderTitle.kt b/core/ui/src/main/java/com/ujizin/leafy/core/ui/components/header/HeaderTitle.kt index 96888fb6..f5dd8e58 100644 --- a/core/ui/src/main/java/com/ujizin/leafy/core/ui/components/header/HeaderTitle.kt +++ b/core/ui/src/main/java/com/ujizin/leafy/core/ui/components/header/HeaderTitle.kt @@ -45,21 +45,12 @@ fun HeaderTitle( @Composable private fun PreviewHeaderTitleWithSubtitle() { LeafyTheme { - HeaderTitle( - title = "Hi Lucas", - subTitle = "Welcome back!", - animation = Animation.None, - ) + HeaderTitle(title = "Hi Lucas", subTitle = "Welcome back!", animation = Animation.None) } } @Preview("Header Title") @Composable private fun PreviewHeaderTitle() { - LeafyTheme { - HeaderTitle( - title = "Hi Lucas", - animation = Animation.None, - ) - } + LeafyTheme { HeaderTitle(title = "Hi Lucas", animation = Animation.None) } } diff --git a/core/ui/src/main/java/com/ujizin/leafy/core/ui/components/image/BoxImage.kt b/core/ui/src/main/java/com/ujizin/leafy/core/ui/components/image/BoxImage.kt index 649d8218..be11bb71 100644 --- a/core/ui/src/main/java/com/ujizin/leafy/core/ui/components/image/BoxImage.kt +++ b/core/ui/src/main/java/com/ujizin/leafy/core/ui/components/image/BoxImage.kt @@ -32,11 +32,13 @@ fun BoxImage( contentDescription = contentDescription, ) Box( - modifier = Modifier - .fillMaxSize() - .innerShadow(Shadow.Black, RoundedCornerShape(4.dp)) - .padding(12.dp), + modifier = + Modifier.fillMaxSize() + .innerShadow(Shadow.Black, RoundedCornerShape(4.dp)) + .padding(12.dp), contentAlignment = contentAlignment, - ) { content() } + ) { + content() + } } } diff --git a/core/ui/src/main/java/com/ujizin/leafy/core/ui/components/modal/ModalBottomSheet.kt b/core/ui/src/main/java/com/ujizin/leafy/core/ui/components/modal/ModalBottomSheet.kt index ee442159..2be9f20b 100644 --- a/core/ui/src/main/java/com/ujizin/leafy/core/ui/components/modal/ModalBottomSheet.kt +++ b/core/ui/src/main/java/com/ujizin/leafy/core/ui/components/modal/ModalBottomSheet.kt @@ -20,14 +20,11 @@ fun ModalBottomSheet( content: @Composable ColumnScope.() -> Unit, ) { var isAnimating by remember(Unit) { mutableStateOf(showModal) } - val modalState = rememberModalBottomSheetState( - skipPartiallyExpanded = skipPartiallyExpanded, - ) + val modalState = rememberModalBottomSheetState(skipPartiallyExpanded = skipPartiallyExpanded) LaunchedEffect(showModal) { - launch { - if (showModal) modalState.show() else modalState.hide() - }.invokeOnCompletion { isAnimating = showModal } + launch { if (showModal) modalState.show() else modalState.hide() } + .invokeOnCompletion { isAnimating = showModal } } if (showModal || isAnimating) { diff --git a/core/ui/src/main/java/com/ujizin/leafy/core/ui/components/navigation/NavItem.kt b/core/ui/src/main/java/com/ujizin/leafy/core/ui/components/navigation/NavItem.kt index 13971bc8..24566cfc 100644 --- a/core/ui/src/main/java/com/ujizin/leafy/core/ui/components/navigation/NavItem.kt +++ b/core/ui/src/main/java/com/ujizin/leafy/core/ui/components/navigation/NavItem.kt @@ -8,11 +8,8 @@ import com.ujizin.leafy.core.ui.components.navigation.drawer.DrawerItem * NavItem is used for components that needs to be navigated to one destination. * * Used in [BottomNavItem] & [DrawerItem]. - * - * */ + */ interface NavItem { - /** - * Item destination. - * */ + /** Item destination. */ val destination: Destination } diff --git a/core/ui/src/main/java/com/ujizin/leafy/core/ui/components/navigation/NavigationExtensions.kt b/core/ui/src/main/java/com/ujizin/leafy/core/ui/components/navigation/NavigationExtensions.kt index faeab3d1..5f8bbfe9 100644 --- a/core/ui/src/main/java/com/ujizin/leafy/core/ui/components/navigation/NavigationExtensions.kt +++ b/core/ui/src/main/java/com/ujizin/leafy/core/ui/components/navigation/NavigationExtensions.kt @@ -16,25 +16,28 @@ import androidx.navigation.NavController import com.ujizin.leafy.core.navigation.qualifiedRoute import com.ujizin.leafy.core.ui.components.navigation.bottombar.BottomNavItem -val ExitTransition?.orNone get() = this ?: ExitTransition.None +val ExitTransition?.orNone + get() = this ?: ExitTransition.None private enum class NavDirection { - Start, End, None, + Start, + End, + None, } -private fun navDirection( - navController: NavController, -): NavDirection { +private fun navDirection(navController: NavController): NavDirection { val previousDestination = navController.previousBackStackEntry?.destination?.qualifiedRoute val currentDestination = navController.currentBackStackEntry?.destination?.qualifiedRoute - val previousBottomNavItem = BottomNavItem.entries.firstOrNull { - it.destination::class.qualifiedName == previousDestination - } ?: return NavDirection.End + val previousBottomNavItem = + BottomNavItem.entries.firstOrNull { + it.destination::class.qualifiedName == previousDestination + } ?: return NavDirection.End - val currentBottomNavItem = BottomNavItem.entries.firstOrNull { - it.destination::class.qualifiedName == currentDestination - } ?: return NavDirection.End + val currentBottomNavItem = + BottomNavItem.entries.firstOrNull { + it.destination::class.qualifiedName == currentDestination + } ?: return NavDirection.End if (currentBottomNavItem == BottomNavItem.Camera) return NavDirection.None @@ -45,59 +48,55 @@ private fun navDirection( } fun AnimatedContentTransitionScope<*>.navigationEnterTransition( - navController: NavController, + navController: NavController ): EnterTransition? { - val direction = when (navDirection(navController)) { - NavDirection.Start -> AnimatedContentTransitionScope.SlideDirection.Start - NavDirection.End -> AnimatedContentTransitionScope.SlideDirection.End - NavDirection.None -> null - } ?: return null + val direction = + when (navDirection(navController)) { + NavDirection.Start -> AnimatedContentTransitionScope.SlideDirection.Start + NavDirection.End -> AnimatedContentTransitionScope.SlideDirection.End + NavDirection.None -> null + } ?: return null return slideIntoContainer( direction, - animationSpec = spring( - Spring.DampingRatioLowBouncy, - Spring.StiffnessMediumLow, - ), + animationSpec = spring(Spring.DampingRatioLowBouncy, Spring.StiffnessMediumLow), ) + fadeIn() } fun AnimatedContentTransitionScope<*>.navigationExitTransition( - navController: NavController, + navController: NavController ): ExitTransition? { - val direction = when (navDirection(navController)) { - NavDirection.Start -> AnimatedContentTransitionScope.SlideDirection.Start - NavDirection.End -> AnimatedContentTransitionScope.SlideDirection.End - NavDirection.None -> null - } ?: return null + val direction = + when (navDirection(navController)) { + NavDirection.Start -> AnimatedContentTransitionScope.SlideDirection.Start + NavDirection.End -> AnimatedContentTransitionScope.SlideDirection.End + NavDirection.None -> null + } ?: return null return slideOutOfContainer( direction, - animationSpec = spring( - Spring.DampingRatioNoBouncy, - Spring.StiffnessMedium, - ), + animationSpec = spring(Spring.DampingRatioNoBouncy, Spring.StiffnessMedium), ) + fadeOut() } @Composable internal inline fun NavController.currentNavItemAsState( - initialNavItem: T? = null, + initialNavItem: T? = null ): State { val selectedItem = remember(initialNavItem) { mutableStateOf(initialNavItem) } DisposableEffect(this) { - val listener = NavController.OnDestinationChangedListener { _, destination, _ -> - val currentDestination = destination.qualifiedRoute - val value = T::class.java.enumConstants?.firstOrNull { - it.destination::class.qualifiedName == currentDestination + val listener = + NavController.OnDestinationChangedListener { _, destination, _ -> + val currentDestination = destination.qualifiedRoute + val value = + T::class.java.enumConstants?.firstOrNull { + it.destination::class.qualifiedName == currentDestination + } + selectedItem.value = value } - selectedItem.value = value - } addOnDestinationChangedListener(listener) - onDispose { - removeOnDestinationChangedListener(listener) - } + onDispose { removeOnDestinationChangedListener(listener) } } return selectedItem diff --git a/core/ui/src/main/java/com/ujizin/leafy/core/ui/components/navigation/bottombar/NavigationBar.kt b/core/ui/src/main/java/com/ujizin/leafy/core/ui/components/navigation/bottombar/NavigationBar.kt index 4d592aab..56dbac46 100644 --- a/core/ui/src/main/java/com/ujizin/leafy/core/ui/components/navigation/bottombar/NavigationBar.kt +++ b/core/ui/src/main/java/com/ujizin/leafy/core/ui/components/navigation/bottombar/NavigationBar.kt @@ -18,25 +18,22 @@ import com.ujizin.leafy.core.ui.components.navigation.currentNavItemAsState import com.ujizin.leafy.core.ui.state.keyboardAsState @Composable -internal fun NavigationBar( - navController: NavController, -) { +internal fun NavigationBar(navController: NavController) { val navItem by navController.currentNavItemAsState(BottomNavItem.Home) val isKeyboardOpen by keyboardAsState() - val isBottomNavItem = remember(navItem) { - BottomNavItem.entries.any { bottomNavItem -> - bottomNavItem.destination != Destination.Camera && - bottomNavItem.destination == navItem?.destination + val isBottomNavItem = + remember(navItem) { + BottomNavItem.entries.any { bottomNavItem -> + bottomNavItem.destination != Destination.Camera && + bottomNavItem.destination == navItem?.destination + } } - } BottomNavigationBar( bottomNavItem = navItem, showBottomNavigation = isBottomNavItem && !isKeyboardOpen, bottomNavItems = remember { BottomNavItem.entries.toList() }, - onNavItemClicked = { destination -> - navController.navigateToItem(destination) - }, + onNavItemClicked = { destination -> navController.navigateToItem(destination) }, ) } @@ -51,23 +48,19 @@ private fun BottomNavigationBar( Box(modifier = modifier) { Animated( visibleTarget = showBottomNavigation, - animation = Animation.SlideToTop.copy( - durationMillis = Animation.SMALL_DURATION, - ), + animation = Animation.SlideToTop.copy(durationMillis = Animation.SMALL_DURATION), ) { androidx.compose.material3.NavigationBar { bottomNavItems.forEach { item -> - NavBarItem(selectedItem = bottomNavItem, item = item, onClick = { - onNavItemClicked(item) - }) + NavBarItem( + selectedItem = bottomNavItem, + item = item, + onClick = { onNavItemClicked(item) }, + ) } } - CameraButton( - modifier = Modifier - .fillMaxWidth() - .offset(y = (-32).dp), - ) { + CameraButton(modifier = Modifier.fillMaxWidth().offset(y = (-32).dp)) { onNavItemClicked(BottomNavItem.Camera) } } @@ -76,11 +69,7 @@ private fun BottomNavigationBar( fun NavController.navigateToItem(item: NavItem) { navigate(item.destination) { - graph.startDestinationRoute?.let { route -> - popUpTo(route) { - saveState = true - } - } + graph.startDestinationRoute?.let { route -> popUpTo(route) { saveState = true } } launchSingleTop = true restoreState = true } diff --git a/core/ui/src/main/java/com/ujizin/leafy/core/ui/components/navigation/drawer/DrawerContent.kt b/core/ui/src/main/java/com/ujizin/leafy/core/ui/components/navigation/drawer/DrawerContent.kt index c5e19036..fe849eb2 100644 --- a/core/ui/src/main/java/com/ujizin/leafy/core/ui/components/navigation/drawer/DrawerContent.kt +++ b/core/ui/src/main/java/com/ujizin/leafy/core/ui/components/navigation/drawer/DrawerContent.kt @@ -34,9 +34,7 @@ internal fun DrawerContent( ModalDrawerSheet(modifier) { Column(Modifier.padding(horizontal = 12.dp, vertical = 32.dp)) { HeaderTitle( - modifier = Modifier - .fillMaxWidth() - .clickable(onClick = onUserClick), + modifier = Modifier.fillMaxWidth().clickable(onClick = onUserClick), title = LocalUser.current.nickname, subTitle = stringResource(R.string.edit_name).capitalize(), ) @@ -72,9 +70,7 @@ private fun DrawerItems( }, label = { Text(text = stringResource(id = item.labelRes).capitalize()) }, selected = isSelected, - onClick = { - if (isSelected) onCloseDrawer() else onDrawerClicked(item) - }, + onClick = { if (isSelected) onCloseDrawer() else onDrawerClicked(item) }, ) } } diff --git a/core/ui/src/main/java/com/ujizin/leafy/core/ui/components/scaffold/Scaffold.kt b/core/ui/src/main/java/com/ujizin/leafy/core/ui/components/scaffold/Scaffold.kt index c2b38f43..0001f7bf 100644 --- a/core/ui/src/main/java/com/ujizin/leafy/core/ui/components/scaffold/Scaffold.kt +++ b/core/ui/src/main/java/com/ujizin/leafy/core/ui/components/scaffold/Scaffold.kt @@ -20,9 +20,7 @@ fun Scaffold( content: @Composable ColumnScope.() -> Unit, ) { Column(modifier, content = content) - Box(modifier = Modifier.padding(24.dp)) { - topBar() - } + Box(modifier = Modifier.padding(24.dp)) { topBar() } } @Composable @@ -30,13 +28,8 @@ fun TopAppBar( onNavigationContent: @Composable Content, onActionContent: @Composable RowScope.() -> Unit = {}, ) { - Row( - modifier = Modifier.fillMaxWidth(), - horizontalArrangement = Arrangement.SpaceBetween, - ) { + Row(modifier = Modifier.fillMaxWidth(), horizontalArrangement = Arrangement.SpaceBetween) { onNavigationContent() - Row { - onActionContent() - } + Row { onActionContent() } } } diff --git a/core/ui/src/main/java/com/ujizin/leafy/core/ui/components/selector/ModalSelector.kt b/core/ui/src/main/java/com/ujizin/leafy/core/ui/components/selector/ModalSelector.kt index 4eeed7fa..9ae5cc66 100644 --- a/core/ui/src/main/java/com/ujizin/leafy/core/ui/components/selector/ModalSelector.kt +++ b/core/ui/src/main/java/com/ujizin/leafy/core/ui/components/selector/ModalSelector.kt @@ -40,9 +40,7 @@ fun ModalSelector( LazyColumn { items(values) { value -> ModalItemSelector( - Modifier - .fillMaxWidth() - .padding(horizontal = 20.dp, vertical = 16.dp), + Modifier.fillMaxWidth().padding(horizontal = 20.dp, vertical = 16.dp), text = value.name.capitalize(), enabled = enabled, selected = currentValue == value, @@ -63,27 +61,30 @@ fun ModalItemSelector( onItemSelectorClicked: () -> Unit, ) { Row( - modifier = Modifier - .then(if (enabled) Modifier.clickable(onClick = onItemSelectorClicked) else Modifier) - .then(modifier), + modifier = + Modifier.then( + if (enabled) Modifier.clickable(onClick = onItemSelectorClicked) else Modifier + ) + .then(modifier), horizontalArrangement = Arrangement.SpaceBetween, ) { Text(text = text) Box( - modifier = Modifier - .background(MaterialTheme.colorScheme.primary, CircleShape) - .size(24.dp) - .padding(8.dp) - .then( - when { - selected -> Modifier.background( - MaterialTheme.colorScheme.onPrimary, - CircleShape, - ) + modifier = + Modifier.background(MaterialTheme.colorScheme.primary, CircleShape) + .size(24.dp) + .padding(8.dp) + .then( + when { + selected -> + Modifier.background( + MaterialTheme.colorScheme.onPrimary, + CircleShape, + ) - else -> Modifier - }, - ), + else -> Modifier + } + ) ) } } diff --git a/core/ui/src/main/java/com/ujizin/leafy/core/ui/components/selector/ModalValue.kt b/core/ui/src/main/java/com/ujizin/leafy/core/ui/components/selector/ModalValue.kt index 6c03fa84..9f26a45b 100644 --- a/core/ui/src/main/java/com/ujizin/leafy/core/ui/components/selector/ModalValue.kt +++ b/core/ui/src/main/java/com/ujizin/leafy/core/ui/components/selector/ModalValue.kt @@ -1,6 +1,3 @@ package com.ujizin.leafy.core.ui.components.selector -data class ModalValue( - val name: String, - val value: T, -) +data class ModalValue(val name: String, val value: T) diff --git a/core/ui/src/main/java/com/ujizin/leafy/core/ui/components/selector/Selector.kt b/core/ui/src/main/java/com/ujizin/leafy/core/ui/components/selector/Selector.kt index cf7c5607..55abc385 100644 --- a/core/ui/src/main/java/com/ujizin/leafy/core/ui/components/selector/Selector.kt +++ b/core/ui/src/main/java/com/ujizin/leafy/core/ui/components/selector/Selector.kt @@ -41,9 +41,7 @@ fun Selector( onModalStateChanged = onModalStateChanged, content = content, ) - ButtonRow(modifier, title, subTitle, value) { - onModalStateChanged(true) - } + ButtonRow(modifier, title, subTitle, value) { onModalStateChanged(true) } } @Composable @@ -56,9 +54,7 @@ fun ButtonRow( onClick: () -> Unit, ) { Row( - modifier = Modifier - .clickable(onClick = onClick) - .then(modifier), + modifier = Modifier.clickable(onClick = onClick).then(modifier), horizontalArrangement = Arrangement.SpaceBetween, verticalAlignment = Alignment.CenterVertically, ) { @@ -74,8 +70,7 @@ fun ButtonRow( Text(text = value.capitalize()) } ArrowIcon( - Modifier - .padding(start = 8.dp) + Modifier.padding(start = 8.dp) .width(arrowDirection.width) .height(arrowDirection.height), direction = arrowDirection, @@ -123,14 +118,10 @@ private fun ArrowIcon( fun PreviewSelector() { LeafyTheme { Selector( - modifier = Modifier - .fillMaxWidth() - .padding(20.dp), + modifier = Modifier.fillMaxWidth().padding(20.dp), title = "ring", value = "rang", - content = { - Text("Foo") - }, + content = { Text("Foo") }, ) } } @@ -140,15 +131,11 @@ fun PreviewSelector() { fun PreviewSelectorWithSubtitle() { LeafyTheme { Selector( - modifier = Modifier - .fillMaxWidth() - .padding(20.dp), + modifier = Modifier.fillMaxWidth().padding(20.dp), title = "ring", subTitle = "rong", value = "rang", - content = { - Text("Foo") - }, + content = { Text("Foo") }, ) } } @@ -158,14 +145,10 @@ fun PreviewSelectorWithSubtitle() { fun PreviewSelectorWithNoValue() { LeafyTheme { Selector( - modifier = Modifier - .fillMaxWidth() - .padding(20.dp), + modifier = Modifier.fillMaxWidth().padding(20.dp), title = "ring", subTitle = "rong", - content = { - Text("Foo") - }, + content = { Text("Foo") }, ) } } diff --git a/core/ui/src/main/java/com/ujizin/leafy/core/ui/components/textfield/TextField.kt b/core/ui/src/main/java/com/ujizin/leafy/core/ui/components/textfield/TextField.kt index bb374bd5..c149aaba 100644 --- a/core/ui/src/main/java/com/ujizin/leafy/core/ui/components/textfield/TextField.kt +++ b/core/ui/src/main/java/com/ujizin/leafy/core/ui/components/textfield/TextField.kt @@ -5,6 +5,7 @@ import androidx.compose.foundation.shape.RoundedCornerShape import androidx.compose.material3.LocalTextStyle import androidx.compose.material3.MaterialTheme import androidx.compose.material3.Text +import androidx.compose.material3.TextField as MaterialTextField import androidx.compose.material3.TextFieldDefaults import androidx.compose.runtime.Composable import androidx.compose.runtime.getValue @@ -22,7 +23,6 @@ import com.ujizin.leafy.core.ui.components.animated.animation.Animate.Animated import com.ujizin.leafy.core.ui.components.animated.animation.Animation import com.ujizin.leafy.core.ui.extensions.Content import com.ujizin.leafy.core.ui.extensions.capitalize -import androidx.compose.material3.TextField as MaterialTextField @Composable fun TextField( @@ -43,11 +43,12 @@ fun TextField( shape = shape, placeholder = placeholder, textStyle = LocalTextStyle.current, - colors = TextFieldDefaults.colors( - cursorColor = MaterialTheme.colorScheme.primary, - focusedIndicatorColor = Color.Transparent, - unfocusedIndicatorColor = Color.Transparent, - ), + colors = + TextFieldDefaults.colors( + cursorColor = MaterialTheme.colorScheme.primary, + focusedIndicatorColor = Color.Transparent, + unfocusedIndicatorColor = Color.Transparent, + ), ) } } @@ -58,10 +59,7 @@ fun Placeholder( leadingIcon: @Composable Content = {}, text: String, ) { - Row( - modifier = modifier, - verticalAlignment = Alignment.CenterVertically, - ) { + Row(modifier = modifier, verticalAlignment = Alignment.CenterVertically) { leadingIcon() Text( diff --git a/core/ui/src/main/java/com/ujizin/leafy/core/ui/extensions/AnimationExtensions.kt b/core/ui/src/main/java/com/ujizin/leafy/core/ui/extensions/AnimationExtensions.kt index 1d5aba53..d0737145 100644 --- a/core/ui/src/main/java/com/ujizin/leafy/core/ui/extensions/AnimationExtensions.kt +++ b/core/ui/src/main/java/com/ujizin/leafy/core/ui/extensions/AnimationExtensions.kt @@ -6,14 +6,10 @@ import androidx.compose.animation.slideOutHorizontally import androidx.compose.animation.slideOutVertically import androidx.compose.runtime.Stable -@Stable -fun fullSlideInHorizontally() = slideInHorizontally { it } +@Stable fun fullSlideInHorizontally() = slideInHorizontally { it } -@Stable -fun fullSlideOutHorizontally() = slideOutHorizontally { it } +@Stable fun fullSlideOutHorizontally() = slideOutHorizontally { it } -@Stable -fun fullSlideInVertically() = slideInVertically { it } +@Stable fun fullSlideInVertically() = slideInVertically { it } -@Stable -fun fullSlideOutVertically() = slideOutVertically { -it } +@Stable fun fullSlideOutVertically() = slideOutVertically { -it } diff --git a/core/ui/src/main/java/com/ujizin/leafy/core/ui/extensions/ContextExtensions.kt b/core/ui/src/main/java/com/ujizin/leafy/core/ui/extensions/ContextExtensions.kt index 544c1c1b..73cfac75 100644 --- a/core/ui/src/main/java/com/ujizin/leafy/core/ui/extensions/ContextExtensions.kt +++ b/core/ui/src/main/java/com/ujizin/leafy/core/ui/extensions/ContextExtensions.kt @@ -8,29 +8,27 @@ import android.provider.Settings import java.io.File fun Context.startSettingsPermission() { - val intent = Intent( - Settings.ACTION_APPLICATION_DETAILS_SETTINGS, - Uri.parse( - "package:$packageName", - ), - ) + val intent = + Intent(Settings.ACTION_APPLICATION_DETAILS_SETTINGS, Uri.parse("package:$packageName")) startActivity(intent) } -val Context.plantsDir get() = File(filesDir, "plants").apply { mkdirs() } +val Context.plantsDir + get() = File(filesDir, "plants").apply { mkdirs() } val Context.versionName - get() = try { - packageManager.getPackageInfo(packageName, 0).versionName - } catch (e: PackageManager.NameNotFoundException) { - null - } + get() = + try { + packageManager.getPackageInfo(packageName, 0).versionName + } catch (e: PackageManager.NameNotFoundException) { + null + } fun Context.openAppInPlayStore() { startActivity( Intent( Intent.ACTION_VIEW, Uri.parse("https://play.google.com/store/apps/details?id=$packageName"), - ), + ) ) } diff --git a/core/ui/src/main/java/com/ujizin/leafy/core/ui/extensions/CoroutineExtensions.kt b/core/ui/src/main/java/com/ujizin/leafy/core/ui/extensions/CoroutineExtensions.kt index 84e79f43..43fa778f 100644 --- a/core/ui/src/main/java/com/ujizin/leafy/core/ui/extensions/CoroutineExtensions.kt +++ b/core/ui/src/main/java/com/ujizin/leafy/core/ui/extensions/CoroutineExtensions.kt @@ -1,9 +1,9 @@ package com.ujizin.leafy.core.ui.extensions +import kotlin.coroutines.CoroutineContext import kotlinx.coroutines.CoroutineExceptionHandler import kotlinx.coroutines.CoroutineScope import kotlinx.coroutines.launch -import kotlin.coroutines.CoroutineContext fun CoroutineScope.launchCatching( exceptionBlock: (CoroutineContext, Throwable) -> Unit, diff --git a/core/ui/src/main/java/com/ujizin/leafy/core/ui/extensions/FileExtensions.kt b/core/ui/src/main/java/com/ujizin/leafy/core/ui/extensions/FileExtensions.kt index 527c91b4..67bf2b72 100644 --- a/core/ui/src/main/java/com/ujizin/leafy/core/ui/extensions/FileExtensions.kt +++ b/core/ui/src/main/java/com/ujizin/leafy/core/ui/extensions/FileExtensions.kt @@ -15,33 +15,36 @@ fun ByteArrayOutputStream.decodeToBitmapWithRotation(): Bitmap? { if (Build.VERSION.SDK_INT < Build.VERSION_CODES.N) return bitmap - val orientation = ExifInterface(ByteArrayInputStream(byteArray)).getAttributeInt( - ExifInterface.TAG_ORIENTATION, - ExifInterface.ORIENTATION_UNDEFINED, - ) - - val degrees = when (orientation) { - ExifInterface.ORIENTATION_ROTATE_90, ExifInterface.ORIENTATION_TRANSPOSE -> 90F - ExifInterface.ORIENTATION_ROTATE_180, ExifInterface.ORIENTATION_FLIP_VERTICAL -> 180F - ExifInterface.ORIENTATION_ROTATE_270 -> 270F - ExifInterface.ORIENTATION_TRANSVERSE -> -90F - else -> 0F - } - - val scale = when (orientation) { - ExifInterface.ORIENTATION_FLIP_HORIZONTAL, - ExifInterface.ORIENTATION_FLIP_VERTICAL, - ExifInterface.ORIENTATION_TRANSPOSE, - ExifInterface.ORIENTATION_TRANSVERSE, - -> -1F to 1F - - else -> 1F to 1F - } - - val matrix = Matrix().apply { - postRotate(degrees) - postScale(scale.first, scale.second) - } + val orientation = + ExifInterface(ByteArrayInputStream(byteArray)) + .getAttributeInt(ExifInterface.TAG_ORIENTATION, ExifInterface.ORIENTATION_UNDEFINED) + + val degrees = + when (orientation) { + ExifInterface.ORIENTATION_ROTATE_90, + ExifInterface.ORIENTATION_TRANSPOSE -> 90F + ExifInterface.ORIENTATION_ROTATE_180, + ExifInterface.ORIENTATION_FLIP_VERTICAL -> 180F + ExifInterface.ORIENTATION_ROTATE_270 -> 270F + ExifInterface.ORIENTATION_TRANSVERSE -> -90F + else -> 0F + } + + val scale = + when (orientation) { + ExifInterface.ORIENTATION_FLIP_HORIZONTAL, + ExifInterface.ORIENTATION_FLIP_VERTICAL, + ExifInterface.ORIENTATION_TRANSPOSE, + ExifInterface.ORIENTATION_TRANSVERSE -> -1F to 1F + + else -> 1F to 1F + } + + val matrix = + Matrix().apply { + postRotate(degrees) + postScale(scale.first, scale.second) + } return Bitmap.createBitmap(bitmap, 0, 0, bitmap.width, bitmap.height, matrix, true) } diff --git a/core/ui/src/main/java/com/ujizin/leafy/core/ui/extensions/ModifierExtensions.kt b/core/ui/src/main/java/com/ujizin/leafy/core/ui/extensions/ModifierExtensions.kt index 58bb8df7..3427feae 100644 --- a/core/ui/src/main/java/com/ujizin/leafy/core/ui/extensions/ModifierExtensions.kt +++ b/core/ui/src/main/java/com/ujizin/leafy/core/ui/extensions/ModifierExtensions.kt @@ -11,17 +11,10 @@ import androidx.compose.ui.graphics.Shape import androidx.compose.ui.unit.Dp import androidx.compose.ui.unit.dp -fun Modifier.innerShadow(colors: List, shape: Shape = RectangleShape) = then( - Modifier.background( - brush = Brush.verticalGradient(colors), - shape = shape, - ), -) +fun Modifier.innerShadow(colors: List, shape: Shape = RectangleShape) = + then(Modifier.background(brush = Brush.verticalGradient(colors), shape = shape)) -fun Modifier.paddingScreen(horizontal: Dp = 20.dp, vertical: Dp = 0.dp) = then( - Modifier.padding(horizontal = horizontal, vertical = vertical), -) +fun Modifier.paddingScreen(horizontal: Dp = 20.dp, vertical: Dp = 0.dp) = + then(Modifier.padding(horizontal = horizontal, vertical = vertical)) -fun Modifier.noClickable() = then( - Modifier.clickable(enabled = false, onClick = {}), -) +fun Modifier.noClickable() = then(Modifier.clickable(enabled = false, onClick = {})) diff --git a/core/ui/src/main/java/com/ujizin/leafy/core/ui/extensions/PlantExtensions.kt b/core/ui/src/main/java/com/ujizin/leafy/core/ui/extensions/PlantExtensions.kt index 6eb074c6..5c2ddab0 100644 --- a/core/ui/src/main/java/com/ujizin/leafy/core/ui/extensions/PlantExtensions.kt +++ b/core/ui/src/main/java/com/ujizin/leafy/core/ui/extensions/PlantExtensions.kt @@ -8,21 +8,20 @@ import com.ujizin.leafy.domain.model.Plant import java.io.File fun Plant.share(context: Context) { - val intent = Intent().apply { - action = Intent.ACTION_SEND - val uri = FileProvider.getUriForFile( - context, - "${context.packageName}.provider", - File(filePath), - ) - setDataAndType(uri, "image/*") - putExtra(Intent.EXTRA_STREAM, uri) - putExtra(Intent.EXTRA_TEXT, "$title - $description") - } + val intent = + Intent().apply { + action = Intent.ACTION_SEND + val uri = + FileProvider.getUriForFile( + context, + "${context.packageName}.provider", + File(filePath), + ) + setDataAndType(uri, "image/*") + putExtra(Intent.EXTRA_STREAM, uri) + putExtra(Intent.EXTRA_TEXT, "$title - $description") + } context.startActivity( - Intent.createChooser( - intent, - context.getString(R.string.plant_share_title).capitalize(), - ), + Intent.createChooser(intent, context.getString(R.string.plant_share_title).capitalize()) ) } diff --git a/core/ui/src/main/java/com/ujizin/leafy/core/ui/extensions/StringExtensions.kt b/core/ui/src/main/java/com/ujizin/leafy/core/ui/extensions/StringExtensions.kt index 6ab1dbb2..a1c8c005 100644 --- a/core/ui/src/main/java/com/ujizin/leafy/core/ui/extensions/StringExtensions.kt +++ b/core/ui/src/main/java/com/ujizin/leafy/core/ui/extensions/StringExtensions.kt @@ -1,6 +1,7 @@ package com.ujizin.leafy.core.ui.extensions -val String.Companion.Empty get() = "" +val String.Companion.Empty + get() = "" fun String.capitalize() = replaceFirstChar { if (it.isLowerCase()) it.titlecase() else it.toString() diff --git a/core/ui/src/main/java/com/ujizin/leafy/core/ui/extensions/WeekDayExtensions.kt b/core/ui/src/main/java/com/ujizin/leafy/core/ui/extensions/WeekDayExtensions.kt index 54644bb9..e4401f59 100644 --- a/core/ui/src/main/java/com/ujizin/leafy/core/ui/extensions/WeekDayExtensions.kt +++ b/core/ui/src/main/java/com/ujizin/leafy/core/ui/extensions/WeekDayExtensions.kt @@ -11,27 +11,23 @@ val currentDay: WeekDay val WeekDay.displayNameRes: Int @StringRes - get() = when (this) { - WeekDay.Sunday -> R.string.sunday - WeekDay.Monday -> R.string.monday - WeekDay.Tuesday -> R.string.tuesday - WeekDay.Wednesday -> R.string.wednesday - WeekDay.Thursday -> R.string.thursday - WeekDay.Friday -> R.string.friday - WeekDay.Saturday -> R.string.saturday + get() = + when (this) { + WeekDay.Sunday -> R.string.sunday + WeekDay.Monday -> R.string.monday + WeekDay.Tuesday -> R.string.tuesday + WeekDay.Wednesday -> R.string.wednesday + WeekDay.Thursday -> R.string.thursday + WeekDay.Friday -> R.string.friday + WeekDay.Saturday -> R.string.saturday + } + +fun WeekDay.getShortDay(context: Context, useCapitalize: Boolean = true) = + context.getString(displayNameRes).substring(0, 3).run { + if (useCapitalize) capitalize() else this } -fun WeekDay.getShortDay( - context: Context, - useCapitalize: Boolean = true, -) = context.getString(displayNameRes).substring(0, 3).run { - if (useCapitalize) capitalize() else this -} - -fun List.getDisplayName( - context: Context, - useCapitalize: Boolean = true, -): String { +fun List.getDisplayName(context: Context, useCapitalize: Boolean = true): String { if (isEmpty()) return String.Empty if (size == WeekDay.entries.size) { @@ -42,11 +38,8 @@ fun List.getDisplayName( val shortNames = map { it.getShortDay(context, useCapitalize) } return when { - isOrdinalConsecutive() -> context.getString( - R.string.day_to_day, - shortNames.first(), - shortNames.last(), - ) + isOrdinalConsecutive() -> + context.getString(R.string.day_to_day, shortNames.first(), shortNames.last()) else -> shortNames.joinToString(separator = ", ") } @@ -54,23 +47,15 @@ fun List.getDisplayName( fun List.reorderByCurrentDay(day: WeekDay = currentDay): List { val sortedList = sortedBy(WeekDay::ordinal) - val index = sortedList.indexOfFirst { - it.ordinal >= day.ordinal - }.coerceAtLeast(0) + val index = sortedList.indexOfFirst { it.ordinal >= day.ordinal }.coerceAtLeast(0) return sortedList.drop(index) + sortedList.take(index) } -fun List.getNearestDay( - hours: Int, - minutes: Int, - day: WeekDay = currentDay, -): WeekDay { +fun List.getNearestDay(hours: Int, minutes: Int, day: WeekDay = currentDay): WeekDay { check(isNotEmpty()) { "List must no be null" } if (size == 1) return first() - return reorderByCurrentDay(day).first { - day != it || !day.isDayAlreadyPassed(hours, minutes) - } + return reorderByCurrentDay(day).first { day != it || !day.isDayAlreadyPassed(hours, minutes) } } operator fun WeekDay.plus(other: Int): WeekDay { diff --git a/core/ui/src/main/java/com/ujizin/leafy/core/ui/local/LocalUser.kt b/core/ui/src/main/java/com/ujizin/leafy/core/ui/local/LocalUser.kt index a353e3f3..2cd4e562 100644 --- a/core/ui/src/main/java/com/ujizin/leafy/core/ui/local/LocalUser.kt +++ b/core/ui/src/main/java/com/ujizin/leafy/core/ui/local/LocalUser.kt @@ -9,19 +9,18 @@ import com.ujizin.leafy.domain.model.User.Settings import java.util.Locale private val DefaultLanguage - get() = when (Locale.getDefault().language) { - "pt" -> PT - else -> EN - } + get() = + when (Locale.getDefault().language) { + "pt" -> PT + else -> EN + } private val DefaultUser: User - get() = User( - nickname = "User", - settings = Settings( - theme = Theme.System, - language = DefaultLanguage, - dynamicColor = true, - ), - ) + get() = + User( + nickname = "User", + settings = + Settings(theme = Theme.System, language = DefaultLanguage, dynamicColor = true), + ) val LocalUser = compositionLocalOf { DefaultUser } diff --git a/core/ui/src/main/java/com/ujizin/leafy/core/ui/props/Shadow.kt b/core/ui/src/main/java/com/ujizin/leafy/core/ui/props/Shadow.kt index 0d0e9451..3e3fef09 100644 --- a/core/ui/src/main/java/com/ujizin/leafy/core/ui/props/Shadow.kt +++ b/core/ui/src/main/java/com/ujizin/leafy/core/ui/props/Shadow.kt @@ -4,8 +4,5 @@ import androidx.compose.ui.graphics.Color object Shadow { - val Black: List = listOf( - Color.Black.copy(0.0F), - Color.Black.copy(0.75F), - ) + val Black: List = listOf(Color.Black.copy(0.0F), Color.Black.copy(0.75F)) } diff --git a/core/ui/src/main/java/com/ujizin/leafy/core/ui/state/LifecycleState.kt b/core/ui/src/main/java/com/ujizin/leafy/core/ui/state/LifecycleState.kt index 7f51f68f..245fbbe0 100644 --- a/core/ui/src/main/java/com/ujizin/leafy/core/ui/state/LifecycleState.kt +++ b/core/ui/src/main/java/com/ujizin/leafy/core/ui/state/LifecycleState.kt @@ -12,13 +12,9 @@ import androidx.lifecycle.LifecycleEventObserver fun Lifecycle.observeAsState(): State { val state = remember { mutableStateOf(Lifecycle.Event.ON_ANY) } DisposableEffect(this) { - val observer = LifecycleEventObserver { _, event -> - state.value = event - } + val observer = LifecycleEventObserver { _, event -> state.value = event } this@observeAsState.addObserver(observer) - onDispose { - this@observeAsState.removeObserver(observer) - } + onDispose { this@observeAsState.removeObserver(observer) } } return state } diff --git a/domain/build.gradle.kts b/domain/build.gradle.kts index b17961c6..aca73886 100644 --- a/domain/build.gradle.kts +++ b/domain/build.gradle.kts @@ -1,12 +1,6 @@ -plugins { - alias(libs.plugins.android.library) -} - -apply(from = "../config-android.gradle") +plugins { id("com.ujizin.android-library") } -android { - namespace = "com.ujizin.leafy.domain" -} +android { namespace = "com.ujizin.leafy.domain" } dependencies { testImplementation(libs.mockk) diff --git a/domain/src/main/java/com/ujizin/leafy/domain/dispatcher/DispatcherAnnotations.kt b/domain/src/main/java/com/ujizin/leafy/domain/dispatcher/DispatcherAnnotations.kt index c8edac37..bc35ba0c 100644 --- a/domain/src/main/java/com/ujizin/leafy/domain/dispatcher/DispatcherAnnotations.kt +++ b/domain/src/main/java/com/ujizin/leafy/domain/dispatcher/DispatcherAnnotations.kt @@ -2,10 +2,6 @@ package com.ujizin.leafy.domain.dispatcher import javax.inject.Qualifier -@Qualifier -@Retention(AnnotationRetention.BINARY) -annotation class IoDispatcher +@Qualifier @Retention(AnnotationRetention.BINARY) annotation class IoDispatcher -@Qualifier -@Retention(AnnotationRetention.BINARY) -annotation class DefaultDispatcher +@Qualifier @Retention(AnnotationRetention.BINARY) annotation class DefaultDispatcher diff --git a/domain/src/main/java/com/ujizin/leafy/domain/dispatcher/DispatcherModule.kt b/domain/src/main/java/com/ujizin/leafy/domain/dispatcher/DispatcherModule.kt index 1a1b560b..80c7a790 100644 --- a/domain/src/main/java/com/ujizin/leafy/domain/dispatcher/DispatcherModule.kt +++ b/domain/src/main/java/com/ujizin/leafy/domain/dispatcher/DispatcherModule.kt @@ -10,11 +10,7 @@ import kotlinx.coroutines.Dispatchers @InstallIn(SingletonComponent::class) object DispatcherModule { - @Provides - @IoDispatcher - fun provideIoDispatcher() = Dispatchers.IO + @Provides @IoDispatcher fun provideIoDispatcher() = Dispatchers.IO - @Provides - @DefaultDispatcher - fun provideDefaultDispatcher() = Dispatchers.Default + @Provides @DefaultDispatcher fun provideDefaultDispatcher() = Dispatchers.Default } diff --git a/domain/src/main/java/com/ujizin/leafy/domain/model/Alarm.kt b/domain/src/main/java/com/ujizin/leafy/domain/model/Alarm.kt index a55e73e4..9e0debfd 100644 --- a/domain/src/main/java/com/ujizin/leafy/domain/model/Alarm.kt +++ b/domain/src/main/java/com/ujizin/leafy/domain/model/Alarm.kt @@ -1,16 +1,16 @@ package com.ujizin.leafy.domain.model -/*** - * Alarm Model +/** + * Alarm Model * - * @param id the alarm id - * @param plantId the plant's id - * @param ringtoneUriContent the alarm's ringtone - * @param hours the alarm's hours - * @param enabled check if alarm is enabled or not - * @param minutes the alarm's minutes - * @param weekDays day of the week for alarm - * */ + * @param id the alarm id + * @param plantId the plant's id + * @param ringtoneUriContent the alarm's ringtone + * @param hours the alarm's hours + * @param enabled check if alarm is enabled or not + * @param minutes the alarm's minutes + * @param weekDays day of the week for alarm + */ data class Alarm( val id: Long = 0, val plantId: Long, diff --git a/domain/src/main/java/com/ujizin/leafy/domain/model/Album.kt b/domain/src/main/java/com/ujizin/leafy/domain/model/Album.kt index 9b748937..8a4a3fa3 100644 --- a/domain/src/main/java/com/ujizin/leafy/domain/model/Album.kt +++ b/domain/src/main/java/com/ujizin/leafy/domain/model/Album.kt @@ -1,12 +1,9 @@ package com.ujizin.leafy.domain.model -/*** +/** * Album Model * * @param id the album id * @param title the album title - * */ -data class Album( - val id: Long = 0, - val title: String, -) + */ +data class Album(val id: Long = 0, val title: String) diff --git a/domain/src/main/java/com/ujizin/leafy/domain/model/Language.kt b/domain/src/main/java/com/ujizin/leafy/domain/model/Language.kt index 10195732..a1eb5928 100644 --- a/domain/src/main/java/com/ujizin/leafy/domain/model/Language.kt +++ b/domain/src/main/java/com/ujizin/leafy/domain/model/Language.kt @@ -1,5 +1,6 @@ package com.ujizin.leafy.domain.model enum class Language { - PT, EN + PT, + EN, } diff --git a/domain/src/main/java/com/ujizin/leafy/domain/model/Plant.kt b/domain/src/main/java/com/ujizin/leafy/domain/model/Plant.kt index eb79e5a5..54ced94b 100644 --- a/domain/src/main/java/com/ujizin/leafy/domain/model/Plant.kt +++ b/domain/src/main/java/com/ujizin/leafy/domain/model/Plant.kt @@ -1,6 +1,6 @@ package com.ujizin.leafy.domain.model -/*** +/** * Plant Model * * @param id the plant id diff --git a/domain/src/main/java/com/ujizin/leafy/domain/model/Ringtone.kt b/domain/src/main/java/com/ujizin/leafy/domain/model/Ringtone.kt index 1eb5acd8..0253cd04 100644 --- a/domain/src/main/java/com/ujizin/leafy/domain/model/Ringtone.kt +++ b/domain/src/main/java/com/ujizin/leafy/domain/model/Ringtone.kt @@ -6,9 +6,5 @@ package com.ujizin.leafy.domain.model * @param id ringtone's id * @param title ringtone's title * @param uri ringtone's uri - * */ -data class Ringtone( - val id: String, - val title: String, - val uriContent: String, -) + */ +data class Ringtone(val id: String, val title: String, val uriContent: String) diff --git a/domain/src/main/java/com/ujizin/leafy/domain/model/Theme.kt b/domain/src/main/java/com/ujizin/leafy/domain/model/Theme.kt index 74b1645e..9bda5c40 100644 --- a/domain/src/main/java/com/ujizin/leafy/domain/model/Theme.kt +++ b/domain/src/main/java/com/ujizin/leafy/domain/model/Theme.kt @@ -1,5 +1,7 @@ package com.ujizin.leafy.domain.model enum class Theme { - System, Dark, Light + System, + Dark, + Light, } diff --git a/domain/src/main/java/com/ujizin/leafy/domain/model/User.kt b/domain/src/main/java/com/ujizin/leafy/domain/model/User.kt index 1d6f054b..839c5c66 100644 --- a/domain/src/main/java/com/ujizin/leafy/domain/model/User.kt +++ b/domain/src/main/java/com/ujizin/leafy/domain/model/User.kt @@ -5,11 +5,8 @@ package com.ujizin.leafy.domain.model * * @param nickname nickname from user * @param settings settings from user - * */ -data class User( - val nickname: String, - val settings: Settings, -) { + */ +data class User(val nickname: String, val settings: Settings) { /** * Settings from user. @@ -17,27 +14,23 @@ data class User( * @param theme user theme * @param language user language * @param dynamicColor check if user uses dynamic color - * */ - data class Settings( - val theme: Theme, - val language: Language, - val dynamicColor: Boolean, - ) + */ + data class Settings(val theme: Theme, val language: Language, val dynamicColor: Boolean) } -/** - * update user fields. - * */ +/** update user fields. */ fun User.update( nickname: String? = null, theme: Theme? = null, language: Language? = null, dynamicColor: Boolean? = null, -) = copy( - nickname = nickname ?: this.nickname, - settings = settings.copy( - theme = theme ?: settings.theme, - language = language ?: settings.language, - dynamicColor = dynamicColor ?: settings.dynamicColor, - ), -) +) = + copy( + nickname = nickname ?: this.nickname, + settings = + settings.copy( + theme = theme ?: settings.theme, + language = language ?: settings.language, + dynamicColor = dynamicColor ?: settings.dynamicColor, + ), + ) diff --git a/domain/src/main/java/com/ujizin/leafy/domain/repository/AlarmRepository.kt b/domain/src/main/java/com/ujizin/leafy/domain/repository/AlarmRepository.kt index a2caad50..cb5b4108 100644 --- a/domain/src/main/java/com/ujizin/leafy/domain/repository/AlarmRepository.kt +++ b/domain/src/main/java/com/ujizin/leafy/domain/repository/AlarmRepository.kt @@ -3,48 +3,44 @@ package com.ujizin.leafy.domain.repository import com.ujizin.leafy.domain.model.Alarm import kotlinx.coroutines.flow.Flow -/** - * Interface to Alarm Repository implementation. - * */ +/** Interface to Alarm Repository implementation. */ interface AlarmRepository { /** * Insert new alarm on data source. * * @param alarm alarm to be added - * */ + */ fun insertAlarm(alarm: Alarm): Flow /** * Get alarms by plant id. * * @param plantId the plant's id - * */ + */ fun getAlarms(plantId: Long): Flow> - /** - * Get all alarms. - * */ + /** Get all alarms. */ fun getAllAlarms(): Flow> /** * Get alarm by id. * * @param id the alarm's id - * */ + */ fun getAlarmById(id: Long): Flow /** * Update alarm on data source. * * @param alarm alarm to be updated - * */ + */ fun updateAlarm(alarm: Alarm): Flow /** * Delete alarms on data source by plant id. * * @param plantId the alarms plant's id to be deleted - * */ + */ fun deleteAlarmByPlantId(plantId: Long): Flow } diff --git a/domain/src/main/java/com/ujizin/leafy/domain/repository/AlbumRepository.kt b/domain/src/main/java/com/ujizin/leafy/domain/repository/AlbumRepository.kt index 2c465c53..165784e2 100644 --- a/domain/src/main/java/com/ujizin/leafy/domain/repository/AlbumRepository.kt +++ b/domain/src/main/java/com/ujizin/leafy/domain/repository/AlbumRepository.kt @@ -1,6 +1,4 @@ package com.ujizin.leafy.domain.repository -/** - * Interface to Album Repository implementation. - * */ +/** Interface to Album Repository implementation. */ interface AlbumRepository diff --git a/domain/src/main/java/com/ujizin/leafy/domain/repository/FileRepository.kt b/domain/src/main/java/com/ujizin/leafy/domain/repository/FileRepository.kt index c158ec99..daa25d42 100644 --- a/domain/src/main/java/com/ujizin/leafy/domain/repository/FileRepository.kt +++ b/domain/src/main/java/com/ujizin/leafy/domain/repository/FileRepository.kt @@ -10,6 +10,6 @@ interface FileRepository { * @param parentFile the parent file where's to be saved. * @param bitmap the bitmap to be saved. * @param extension extension from file. - * */ + */ fun saveBitmap(parentFile: File, bitmap: Bitmap, extension: String): File } diff --git a/domain/src/main/java/com/ujizin/leafy/domain/repository/PlantRepository.kt b/domain/src/main/java/com/ujizin/leafy/domain/repository/PlantRepository.kt index f5f3d362..c71343bc 100644 --- a/domain/src/main/java/com/ujizin/leafy/domain/repository/PlantRepository.kt +++ b/domain/src/main/java/com/ujizin/leafy/domain/repository/PlantRepository.kt @@ -3,71 +3,69 @@ package com.ujizin.leafy.domain.repository import com.ujizin.leafy.domain.model.Plant import kotlinx.coroutines.flow.Flow -/** - * Interface to Plant Repository implementation. - * */ +/** Interface to Plant Repository implementation. */ interface PlantRepository { /** * Get all plants. * * @return list of [Plant] - * */ + */ fun getPlants(): Flow> /** * Get plant by id. * * @param id the plant's id - * */ + */ fun getPlant(id: Long): Flow /** * Insert plant. * * @param plant plant to be added - * */ + */ fun insertPlant(plant: Plant): Flow /** * Insert a list of plant. * * @param plants list of plant to be added - * */ + */ fun insertPlants(plants: List): Flow /** * Update plant. * * @param plant plant to be updated - * */ + */ fun updatePlant(plant: Plant): Flow /** * Delete plant. * * @param plant plant to be deleted - * */ + */ fun deletePlant(plant: Plant): Flow /** * Get draft plant. * * @return plant hold in memory - * */ + */ fun getDraftPlant(): Flow /** * Update or add draft plant. * * @param plant plant to be added - * */ + */ fun updateDraftPlant(plant: Plant): Flow /** * Find plant by sentence (title or description). * * @param sentence sentence to find plants - * */ + */ fun findPlantBySentence(sentence: String): Flow> } diff --git a/domain/src/main/java/com/ujizin/leafy/domain/repository/RingtoneRepository.kt b/domain/src/main/java/com/ujizin/leafy/domain/repository/RingtoneRepository.kt index 718cf57e..0c7ff1d3 100644 --- a/domain/src/main/java/com/ujizin/leafy/domain/repository/RingtoneRepository.kt +++ b/domain/src/main/java/com/ujizin/leafy/domain/repository/RingtoneRepository.kt @@ -3,13 +3,9 @@ package com.ujizin.leafy.domain.repository import com.ujizin.leafy.domain.model.Ringtone import kotlinx.coroutines.flow.Flow -/** - * Ringtone repository from android system. - * */ +/** Ringtone repository from android system. */ interface RingtoneRepository { - /** - * Get list of ringtone. - * */ + /** Get list of ringtone. */ fun getRingtones(): Flow> } diff --git a/domain/src/main/java/com/ujizin/leafy/domain/repository/UserRepository.kt b/domain/src/main/java/com/ujizin/leafy/domain/repository/UserRepository.kt index efc2ebef..941abf1e 100644 --- a/domain/src/main/java/com/ujizin/leafy/domain/repository/UserRepository.kt +++ b/domain/src/main/java/com/ujizin/leafy/domain/repository/UserRepository.kt @@ -3,22 +3,20 @@ package com.ujizin.leafy.domain.repository import com.ujizin.leafy.domain.model.User import kotlinx.coroutines.flow.Flow -/** - * Interface to User repository implementation - * */ +/** Interface to User repository implementation */ interface UserRepository { /** - * Get user + * Get user * - * @return return an user - * */ + * @return return an user + */ fun getUser(): Flow /** * Update user * * @param user user to be updated - * */ + */ fun updateUser(user: User): Flow } diff --git a/domain/src/main/java/com/ujizin/leafy/domain/result/Result.kt b/domain/src/main/java/com/ujizin/leafy/domain/result/Result.kt index 0518f049..70433fc6 100644 --- a/domain/src/main/java/com/ujizin/leafy/domain/result/Result.kt +++ b/domain/src/main/java/com/ujizin/leafy/domain/result/Result.kt @@ -1,10 +1,10 @@ package com.ujizin.leafy.domain.result -/** - * Result wrapper to use cases. - * */ +/** Result wrapper to use cases. */ sealed interface Result { data class Success(val data: T) : Result + data class Error(val exception: Throwable? = null) : Result + data object Loading : Result } diff --git a/domain/src/main/java/com/ujizin/leafy/domain/result/ResultExtensions.kt b/domain/src/main/java/com/ujizin/leafy/domain/result/ResultExtensions.kt index 0f08f1fe..670b228e 100644 --- a/domain/src/main/java/com/ujizin/leafy/domain/result/ResultExtensions.kt +++ b/domain/src/main/java/com/ujizin/leafy/domain/result/ResultExtensions.kt @@ -7,13 +7,10 @@ import kotlinx.coroutines.flow.map import kotlinx.coroutines.flow.mapNotNull import kotlinx.coroutines.flow.onStart -fun Flow.asResult(): Flow> = map> { - Result.Success(it) -}.onStart { - emit(Result.Loading) -}.catch { - emit(Result.Error(it)) -} +fun Flow.asResult(): Flow> = + map> { Result.Success(it) } + .onStart { emit(Result.Loading) } + .catch { emit(Result.Error(it)) } fun Flow>.mapResult(): Flow = mapNotNull { result -> when (result) { diff --git a/domain/src/main/java/com/ujizin/leafy/domain/usecase/alarm/AlarmModule.kt b/domain/src/main/java/com/ujizin/leafy/domain/usecase/alarm/AlarmModule.kt index c127d719..637aaf24 100644 --- a/domain/src/main/java/com/ujizin/leafy/domain/usecase/alarm/AlarmModule.kt +++ b/domain/src/main/java/com/ujizin/leafy/domain/usecase/alarm/AlarmModule.kt @@ -23,31 +23,26 @@ object AlarmModule { @Provides @Singleton - fun provideAddAlarm( - repository: AlarmRepository, - ): AddAlarmUseCase = AddAlarmUseCaseImpl(repository) + fun provideAddAlarm(repository: AlarmRepository): AddAlarmUseCase = + AddAlarmUseCaseImpl(repository) @Provides @Singleton - fun provideLoadAlarm( - repository: AlarmRepository, - ): LoadAlarmUseCase = LoadAlarmUseCaseImpl(repository) + fun provideLoadAlarm(repository: AlarmRepository): LoadAlarmUseCase = + LoadAlarmUseCaseImpl(repository) @Provides @Singleton - fun provideLoadAlarms( - repository: AlarmRepository, - ): LoadAlarmsUseCase = LoadAlarmsUseCaseImpl(repository) + fun provideLoadAlarms(repository: AlarmRepository): LoadAlarmsUseCase = + LoadAlarmsUseCaseImpl(repository) @Provides @Singleton - fun provideUpdateAlarm( - repository: AlarmRepository, - ): UpdateAlarmUseCase = UpdateAlarmUseCaseImpl(repository) + fun provideUpdateAlarm(repository: AlarmRepository): UpdateAlarmUseCase = + UpdateAlarmUseCaseImpl(repository) @Provides @Singleton - fun provideDeleteAlarm( - repository: AlarmRepository, - ): DeleteAlarmUseCase = DeleteAlarmUseCaseImpl(repository) + fun provideDeleteAlarm(repository: AlarmRepository): DeleteAlarmUseCase = + DeleteAlarmUseCaseImpl(repository) } diff --git a/domain/src/main/java/com/ujizin/leafy/domain/usecase/alarm/add/AddAlarmUseCase.kt b/domain/src/main/java/com/ujizin/leafy/domain/usecase/alarm/add/AddAlarmUseCase.kt index 9cc97978..cd483b9f 100644 --- a/domain/src/main/java/com/ujizin/leafy/domain/usecase/alarm/add/AddAlarmUseCase.kt +++ b/domain/src/main/java/com/ujizin/leafy/domain/usecase/alarm/add/AddAlarmUseCase.kt @@ -3,15 +3,13 @@ package com.ujizin.leafy.domain.usecase.alarm.add import com.ujizin.leafy.domain.model.Alarm import kotlinx.coroutines.flow.Flow -/** - * Add alarm use case. - * */ +/** Add alarm use case. */ interface AddAlarmUseCase { /** * Add alarm on data source. * * @param alarm alarm to be added - * */ + */ operator fun invoke(alarm: Alarm): Flow } diff --git a/domain/src/main/java/com/ujizin/leafy/domain/usecase/alarm/add/AddAlarmUseCaseImpl.kt b/domain/src/main/java/com/ujizin/leafy/domain/usecase/alarm/add/AddAlarmUseCaseImpl.kt index d4e4838f..060a2fa2 100644 --- a/domain/src/main/java/com/ujizin/leafy/domain/usecase/alarm/add/AddAlarmUseCaseImpl.kt +++ b/domain/src/main/java/com/ujizin/leafy/domain/usecase/alarm/add/AddAlarmUseCaseImpl.kt @@ -3,9 +3,7 @@ package com.ujizin.leafy.domain.usecase.alarm.add import com.ujizin.leafy.domain.model.Alarm import com.ujizin.leafy.domain.repository.AlarmRepository -internal class AddAlarmUseCaseImpl( - private val alarmRepository: AlarmRepository, -) : AddAlarmUseCase { +internal class AddAlarmUseCaseImpl(private val alarmRepository: AlarmRepository) : AddAlarmUseCase { override fun invoke(alarm: Alarm) = alarmRepository.insertAlarm(alarm) } diff --git a/domain/src/main/java/com/ujizin/leafy/domain/usecase/alarm/delete/DeleteAlarmUseCase.kt b/domain/src/main/java/com/ujizin/leafy/domain/usecase/alarm/delete/DeleteAlarmUseCase.kt index 1e8040c2..b6dd5224 100644 --- a/domain/src/main/java/com/ujizin/leafy/domain/usecase/alarm/delete/DeleteAlarmUseCase.kt +++ b/domain/src/main/java/com/ujizin/leafy/domain/usecase/alarm/delete/DeleteAlarmUseCase.kt @@ -2,15 +2,13 @@ package com.ujizin.leafy.domain.usecase.alarm.delete import kotlinx.coroutines.flow.Flow -/** - * Delete alarm use case. - * */ +/** Delete alarm use case. */ interface DeleteAlarmUseCase { /** * Delete alarm by plant id. * * @param plantId the alarms plant's id to be deleted - * */ + */ operator fun invoke(plantId: Long): Flow } diff --git a/domain/src/main/java/com/ujizin/leafy/domain/usecase/alarm/delete/DeleteAlarmUseCaseImpl.kt b/domain/src/main/java/com/ujizin/leafy/domain/usecase/alarm/delete/DeleteAlarmUseCaseImpl.kt index bfa4515f..26bce03d 100644 --- a/domain/src/main/java/com/ujizin/leafy/domain/usecase/alarm/delete/DeleteAlarmUseCaseImpl.kt +++ b/domain/src/main/java/com/ujizin/leafy/domain/usecase/alarm/delete/DeleteAlarmUseCaseImpl.kt @@ -2,9 +2,7 @@ package com.ujizin.leafy.domain.usecase.alarm.delete import com.ujizin.leafy.domain.repository.AlarmRepository -class DeleteAlarmUseCaseImpl( - private val repository: AlarmRepository, -) : DeleteAlarmUseCase { +class DeleteAlarmUseCaseImpl(private val repository: AlarmRepository) : DeleteAlarmUseCase { override fun invoke(plantId: Long) = repository.deleteAlarmByPlantId(plantId) } diff --git a/domain/src/main/java/com/ujizin/leafy/domain/usecase/alarm/load/LoadAlarmUseCase.kt b/domain/src/main/java/com/ujizin/leafy/domain/usecase/alarm/load/LoadAlarmUseCase.kt index 9d330ddb..e3a4127c 100644 --- a/domain/src/main/java/com/ujizin/leafy/domain/usecase/alarm/load/LoadAlarmUseCase.kt +++ b/domain/src/main/java/com/ujizin/leafy/domain/usecase/alarm/load/LoadAlarmUseCase.kt @@ -4,17 +4,13 @@ import com.ujizin.leafy.domain.model.Alarm import com.ujizin.leafy.domain.result.Result import kotlinx.coroutines.flow.Flow -/** - * Load alarm use case. - * */ +/** Load alarm use case. */ interface LoadAlarmUseCase { /** * Load alarm on data source. * * @param id the alarm's id - * */ - operator fun invoke( - id: Long, - ): Flow> + */ + operator fun invoke(id: Long): Flow> } diff --git a/domain/src/main/java/com/ujizin/leafy/domain/usecase/alarm/load/LoadAlarmUseCaseImpl.kt b/domain/src/main/java/com/ujizin/leafy/domain/usecase/alarm/load/LoadAlarmUseCaseImpl.kt index e9c72fb2..420ae59f 100644 --- a/domain/src/main/java/com/ujizin/leafy/domain/usecase/alarm/load/LoadAlarmUseCaseImpl.kt +++ b/domain/src/main/java/com/ujizin/leafy/domain/usecase/alarm/load/LoadAlarmUseCaseImpl.kt @@ -3,9 +3,7 @@ package com.ujizin.leafy.domain.usecase.alarm.load import com.ujizin.leafy.domain.repository.AlarmRepository import com.ujizin.leafy.domain.result.asResult -class LoadAlarmUseCaseImpl( - private val repository: AlarmRepository, -) : LoadAlarmUseCase { +class LoadAlarmUseCaseImpl(private val repository: AlarmRepository) : LoadAlarmUseCase { override fun invoke(id: Long) = repository.getAlarmById(id).asResult() } diff --git a/domain/src/main/java/com/ujizin/leafy/domain/usecase/alarm/load/LoadAlarmsUseCase.kt b/domain/src/main/java/com/ujizin/leafy/domain/usecase/alarm/load/LoadAlarmsUseCase.kt index 44b2fd2a..0f3448d7 100644 --- a/domain/src/main/java/com/ujizin/leafy/domain/usecase/alarm/load/LoadAlarmsUseCase.kt +++ b/domain/src/main/java/com/ujizin/leafy/domain/usecase/alarm/load/LoadAlarmsUseCase.kt @@ -4,16 +4,14 @@ import com.ujizin.leafy.domain.model.Alarm import com.ujizin.leafy.domain.result.Result import kotlinx.coroutines.flow.Flow -/** - * Load alarms use case. - * */ +/** Load alarms use case. */ interface LoadAlarmsUseCase { /** * Load alarms. * * @param plantId the plant's id - * */ + */ operator fun invoke(plantId: Long = INVALID_PLANT_ID): Flow>> companion object { diff --git a/domain/src/main/java/com/ujizin/leafy/domain/usecase/alarm/load/LoadAlarmsUseCaseImpl.kt b/domain/src/main/java/com/ujizin/leafy/domain/usecase/alarm/load/LoadAlarmsUseCaseImpl.kt index 58be1019..e4642514 100644 --- a/domain/src/main/java/com/ujizin/leafy/domain/usecase/alarm/load/LoadAlarmsUseCaseImpl.kt +++ b/domain/src/main/java/com/ujizin/leafy/domain/usecase/alarm/load/LoadAlarmsUseCaseImpl.kt @@ -6,15 +6,12 @@ import com.ujizin.leafy.domain.result.Result import com.ujizin.leafy.domain.result.asResult import kotlinx.coroutines.flow.Flow -class LoadAlarmsUseCaseImpl( - private val repository: AlarmRepository, -) : LoadAlarmsUseCase { +class LoadAlarmsUseCaseImpl(private val repository: AlarmRepository) : LoadAlarmsUseCase { - override fun invoke( - plantId: Long, - ): Flow>> = if (plantId != LoadAlarmsUseCase.INVALID_PLANT_ID) { - repository.getAlarms(plantId).asResult() - } else { - repository.getAllAlarms().asResult() - } + override fun invoke(plantId: Long): Flow>> = + if (plantId != LoadAlarmsUseCase.INVALID_PLANT_ID) { + repository.getAlarms(plantId).asResult() + } else { + repository.getAllAlarms().asResult() + } } diff --git a/domain/src/main/java/com/ujizin/leafy/domain/usecase/alarm/update/UpdateAlarmUseCase.kt b/domain/src/main/java/com/ujizin/leafy/domain/usecase/alarm/update/UpdateAlarmUseCase.kt index 6330141a..7e0809b4 100644 --- a/domain/src/main/java/com/ujizin/leafy/domain/usecase/alarm/update/UpdateAlarmUseCase.kt +++ b/domain/src/main/java/com/ujizin/leafy/domain/usecase/alarm/update/UpdateAlarmUseCase.kt @@ -3,15 +3,13 @@ package com.ujizin.leafy.domain.usecase.alarm.update import com.ujizin.leafy.domain.model.Alarm import kotlinx.coroutines.flow.Flow -/** - * Update alarm use case. - * */ +/** Update alarm use case. */ interface UpdateAlarmUseCase { /** * Update alarm on data source. * * @param alarm alarm to be updated - * */ + */ operator fun invoke(alarm: Alarm): Flow } diff --git a/domain/src/main/java/com/ujizin/leafy/domain/usecase/alarm/update/UpdateAlarmUseCaseImpl.kt b/domain/src/main/java/com/ujizin/leafy/domain/usecase/alarm/update/UpdateAlarmUseCaseImpl.kt index 98dea7b0..afa3d750 100644 --- a/domain/src/main/java/com/ujizin/leafy/domain/usecase/alarm/update/UpdateAlarmUseCaseImpl.kt +++ b/domain/src/main/java/com/ujizin/leafy/domain/usecase/alarm/update/UpdateAlarmUseCaseImpl.kt @@ -3,9 +3,7 @@ package com.ujizin.leafy.domain.usecase.alarm.update import com.ujizin.leafy.domain.model.Alarm import com.ujizin.leafy.domain.repository.AlarmRepository -class UpdateAlarmUseCaseImpl( - private val repository: AlarmRepository, -) : UpdateAlarmUseCase { +class UpdateAlarmUseCaseImpl(private val repository: AlarmRepository) : UpdateAlarmUseCase { override fun invoke(alarm: Alarm) = repository.updateAlarm(alarm) } diff --git a/domain/src/main/java/com/ujizin/leafy/domain/usecase/file/FileModule.kt b/domain/src/main/java/com/ujizin/leafy/domain/usecase/file/FileModule.kt index fc5467a3..9925ff1a 100644 --- a/domain/src/main/java/com/ujizin/leafy/domain/usecase/file/FileModule.kt +++ b/domain/src/main/java/com/ujizin/leafy/domain/usecase/file/FileModule.kt @@ -15,7 +15,6 @@ object FileModule { @Provides @Singleton - fun provideSaveFile( - repository: FileRepository, - ): SaveFileUseCase = SaveFileUseCaseImpl(repository) + fun provideSaveFile(repository: FileRepository): SaveFileUseCase = + SaveFileUseCaseImpl(repository) } diff --git a/domain/src/main/java/com/ujizin/leafy/domain/usecase/file/save/SaveFileUseCase.kt b/domain/src/main/java/com/ujizin/leafy/domain/usecase/file/save/SaveFileUseCase.kt index ef5edf62..e95b7ff8 100644 --- a/domain/src/main/java/com/ujizin/leafy/domain/usecase/file/save/SaveFileUseCase.kt +++ b/domain/src/main/java/com/ujizin/leafy/domain/usecase/file/save/SaveFileUseCase.kt @@ -11,10 +11,6 @@ interface SaveFileUseCase { * @param parentFile the parent file where's to be saved. * @param bitmap the bitmap to be saved. * @param extension extension from file. - * */ - operator fun invoke( - parentFile: File, - bitmap: Bitmap, - extension: String, - ): File + */ + operator fun invoke(parentFile: File, bitmap: Bitmap, extension: String): File } diff --git a/domain/src/main/java/com/ujizin/leafy/domain/usecase/file/save/SaveFileUseCaseImpl.kt b/domain/src/main/java/com/ujizin/leafy/domain/usecase/file/save/SaveFileUseCaseImpl.kt index c352d89e..4fa63c5c 100644 --- a/domain/src/main/java/com/ujizin/leafy/domain/usecase/file/save/SaveFileUseCaseImpl.kt +++ b/domain/src/main/java/com/ujizin/leafy/domain/usecase/file/save/SaveFileUseCaseImpl.kt @@ -4,13 +4,8 @@ import android.graphics.Bitmap import com.ujizin.leafy.domain.repository.FileRepository import java.io.File -internal class SaveFileUseCaseImpl( - private val repository: FileRepository, -) : SaveFileUseCase { +internal class SaveFileUseCaseImpl(private val repository: FileRepository) : SaveFileUseCase { - override operator fun invoke( - parentFile: File, - bitmap: Bitmap, - extension: String, - ): File = repository.saveBitmap(parentFile, bitmap, extension) + override operator fun invoke(parentFile: File, bitmap: Bitmap, extension: String): File = + repository.saveBitmap(parentFile, bitmap, extension) } diff --git a/domain/src/main/java/com/ujizin/leafy/domain/usecase/plant/PlantModule.kt b/domain/src/main/java/com/ujizin/leafy/domain/usecase/plant/PlantModule.kt index 8f22ac2e..553549c1 100644 --- a/domain/src/main/java/com/ujizin/leafy/domain/usecase/plant/PlantModule.kt +++ b/domain/src/main/java/com/ujizin/leafy/domain/usecase/plant/PlantModule.kt @@ -29,49 +29,40 @@ object PlantModule { @Provides @Singleton - fun provideLoadAllPlants( - repository: PlantRepository, - ): LoadAllPlantUseCase = LoadAllPlantUseCaseImpl(repository) + fun provideLoadAllPlants(repository: PlantRepository): LoadAllPlantUseCase = + LoadAllPlantUseCaseImpl(repository) @Provides @Singleton - fun provideLoadPlant( - repository: PlantRepository, - ): LoadPlantUseCase = LoadPlantUseCaseImpl(repository) + fun provideLoadPlant(repository: PlantRepository): LoadPlantUseCase = + LoadPlantUseCaseImpl(repository) @Provides @Singleton - fun provideAddPlant( - repository: PlantRepository, - ): AddPlantUseCase = AddPlantUseCaseImpl(repository) + fun provideAddPlant(repository: PlantRepository): AddPlantUseCase = + AddPlantUseCaseImpl(repository) @Provides @Singleton - fun provideFindPlant( - repository: PlantRepository, - ): FindPlantUseCase = FindPlantUseCaseImpl(repository) + fun provideFindPlant(repository: PlantRepository): FindPlantUseCase = + FindPlantUseCaseImpl(repository) @Provides @Singleton - fun provideUpdatePlant( - repository: PlantRepository, - ): UpdatePlant = UpdatePlantImpl(repository) + fun provideUpdatePlant(repository: PlantRepository): UpdatePlant = UpdatePlantImpl(repository) @Provides @Singleton - fun provideDeletePlant( - repository: PlantRepository, - ): DeletePlantUseCase = DeletePlantUseCaseImpl(repository) + fun provideDeletePlant(repository: PlantRepository): DeletePlantUseCase = + DeletePlantUseCaseImpl(repository) @Provides @Singleton - fun provideAddDraftPlant( - repository: PlantRepository, - ): AddDraftPlantUseCase = AddDraftPlantUseCaseImpl(repository) + fun provideAddDraftPlant(repository: PlantRepository): AddDraftPlantUseCase = + AddDraftPlantUseCaseImpl(repository) @Provides @Singleton - fun provideLoadDraftPlant( - repository: PlantRepository, - ): LoadDraftPlantUseCase = LoadDraftPlantUseCaseImpl(repository) + fun provideLoadDraftPlant(repository: PlantRepository): LoadDraftPlantUseCase = + LoadDraftPlantUseCaseImpl(repository) } diff --git a/domain/src/main/java/com/ujizin/leafy/domain/usecase/plant/add/AddDraftPlantUseCase.kt b/domain/src/main/java/com/ujizin/leafy/domain/usecase/plant/add/AddDraftPlantUseCase.kt index facbf26c..ca3a2d28 100644 --- a/domain/src/main/java/com/ujizin/leafy/domain/usecase/plant/add/AddDraftPlantUseCase.kt +++ b/domain/src/main/java/com/ujizin/leafy/domain/usecase/plant/add/AddDraftPlantUseCase.kt @@ -1,11 +1,9 @@ package com.ujizin.leafy.domain.usecase.plant.add -import kotlinx.coroutines.flow.Flow import java.io.File +import kotlinx.coroutines.flow.Flow -/** - * Use case to insert draft plant in the data source. - * */ +/** Use case to insert draft plant in the data source. */ interface AddDraftPlantUseCase { /** @@ -14,7 +12,7 @@ interface AddDraftPlantUseCase { * @param title plant's title to be added * @param file plant's file to be added * @param description plant's description to be added - * */ + */ operator fun invoke( title: String? = null, file: File? = null, diff --git a/domain/src/main/java/com/ujizin/leafy/domain/usecase/plant/add/AddDraftPlantUseCaseImpl.kt b/domain/src/main/java/com/ujizin/leafy/domain/usecase/plant/add/AddDraftPlantUseCaseImpl.kt index f621390b..8c64e53e 100644 --- a/domain/src/main/java/com/ujizin/leafy/domain/usecase/plant/add/AddDraftPlantUseCaseImpl.kt +++ b/domain/src/main/java/com/ujizin/leafy/domain/usecase/plant/add/AddDraftPlantUseCaseImpl.kt @@ -1,28 +1,25 @@ package com.ujizin.leafy.domain.usecase.plant.add import com.ujizin.leafy.domain.repository.PlantRepository +import java.io.File import kotlinx.coroutines.ExperimentalCoroutinesApi import kotlinx.coroutines.flow.Flow import kotlinx.coroutines.flow.flatMapConcat import kotlinx.coroutines.flow.map -import java.io.File -internal class AddDraftPlantUseCaseImpl( - private val plantRepository: PlantRepository, -) : AddDraftPlantUseCase { +internal class AddDraftPlantUseCaseImpl(private val plantRepository: PlantRepository) : + AddDraftPlantUseCase { @OptIn(ExperimentalCoroutinesApi::class) - override fun invoke( - title: String?, - file: File?, - description: String?, - ): Flow = plantRepository.getDraftPlant().map { plant -> - plant.copy( - title = title ?: plant.title, - description = description ?: plant.description, - filePath = file?.path ?: plant.filePath, - ) - }.flatMapConcat { plant -> - plantRepository.updateDraftPlant(plant) - } + override fun invoke(title: String?, file: File?, description: String?): Flow = + plantRepository + .getDraftPlant() + .map { plant -> + plant.copy( + title = title ?: plant.title, + description = description ?: plant.description, + filePath = file?.path ?: plant.filePath, + ) + } + .flatMapConcat { plant -> plantRepository.updateDraftPlant(plant) } } diff --git a/domain/src/main/java/com/ujizin/leafy/domain/usecase/plant/add/AddPlantUseCase.kt b/domain/src/main/java/com/ujizin/leafy/domain/usecase/plant/add/AddPlantUseCase.kt index 46714841..8ba22958 100644 --- a/domain/src/main/java/com/ujizin/leafy/domain/usecase/plant/add/AddPlantUseCase.kt +++ b/domain/src/main/java/com/ujizin/leafy/domain/usecase/plant/add/AddPlantUseCase.kt @@ -3,15 +3,13 @@ package com.ujizin.leafy.domain.usecase.plant.add import com.ujizin.leafy.domain.model.Plant import kotlinx.coroutines.flow.Flow -/** - * Use case to insert plant in the data source. - * */ +/** Use case to insert plant in the data source. */ interface AddPlantUseCase { /** * Add a plant. * * @param plant plants to be added - * */ + */ operator fun invoke(plant: Plant): Flow } diff --git a/domain/src/main/java/com/ujizin/leafy/domain/usecase/plant/add/AddPlantUseCaseImpl.kt b/domain/src/main/java/com/ujizin/leafy/domain/usecase/plant/add/AddPlantUseCaseImpl.kt index 9a6f45f7..1da237e7 100644 --- a/domain/src/main/java/com/ujizin/leafy/domain/usecase/plant/add/AddPlantUseCaseImpl.kt +++ b/domain/src/main/java/com/ujizin/leafy/domain/usecase/plant/add/AddPlantUseCaseImpl.kt @@ -3,9 +3,7 @@ package com.ujizin.leafy.domain.usecase.plant.add import com.ujizin.leafy.domain.model.Plant import com.ujizin.leafy.domain.repository.PlantRepository -internal class AddPlantUseCaseImpl( - private val plantRepository: PlantRepository, -) : AddPlantUseCase { +internal class AddPlantUseCaseImpl(private val plantRepository: PlantRepository) : AddPlantUseCase { override fun invoke(plant: Plant) = plantRepository.insertPlant(plant) } diff --git a/domain/src/main/java/com/ujizin/leafy/domain/usecase/plant/delete/DeletePlantUseCase.kt b/domain/src/main/java/com/ujizin/leafy/domain/usecase/plant/delete/DeletePlantUseCase.kt index 62d31698..9d37efdc 100644 --- a/domain/src/main/java/com/ujizin/leafy/domain/usecase/plant/delete/DeletePlantUseCase.kt +++ b/domain/src/main/java/com/ujizin/leafy/domain/usecase/plant/delete/DeletePlantUseCase.kt @@ -3,15 +3,13 @@ package com.ujizin.leafy.domain.usecase.plant.delete import com.ujizin.leafy.domain.model.Plant import kotlinx.coroutines.flow.Flow -/** - * Use case to delete plant in the data source. - * */ +/** Use case to delete plant in the data source. */ interface DeletePlantUseCase { /** * Delete a plant. * * @param plant plant to be deleted - * */ + */ operator fun invoke(plant: Plant): Flow } diff --git a/domain/src/main/java/com/ujizin/leafy/domain/usecase/plant/delete/DeletePlantUseCaseImpl.kt b/domain/src/main/java/com/ujizin/leafy/domain/usecase/plant/delete/DeletePlantUseCaseImpl.kt index ab8ee6be..1305fc16 100644 --- a/domain/src/main/java/com/ujizin/leafy/domain/usecase/plant/delete/DeletePlantUseCaseImpl.kt +++ b/domain/src/main/java/com/ujizin/leafy/domain/usecase/plant/delete/DeletePlantUseCaseImpl.kt @@ -3,9 +3,8 @@ package com.ujizin.leafy.domain.usecase.plant.delete import com.ujizin.leafy.domain.model.Plant import com.ujizin.leafy.domain.repository.PlantRepository -internal class DeletePlantUseCaseImpl( - private val plantRepository: PlantRepository, -) : DeletePlantUseCase { +internal class DeletePlantUseCaseImpl(private val plantRepository: PlantRepository) : + DeletePlantUseCase { override fun invoke(plant: Plant) = plantRepository.deletePlant(plant) } diff --git a/domain/src/main/java/com/ujizin/leafy/domain/usecase/plant/find/FindPlantUseCase.kt b/domain/src/main/java/com/ujizin/leafy/domain/usecase/plant/find/FindPlantUseCase.kt index 47451a78..58a0a29e 100644 --- a/domain/src/main/java/com/ujizin/leafy/domain/usecase/plant/find/FindPlantUseCase.kt +++ b/domain/src/main/java/com/ujizin/leafy/domain/usecase/plant/find/FindPlantUseCase.kt @@ -4,15 +4,13 @@ import com.ujizin.leafy.domain.model.Plant import com.ujizin.leafy.domain.result.Result import kotlinx.coroutines.flow.Flow -/** - * Find plant use case. - * */ +/** Find plant use case. */ interface FindPlantUseCase { /** * Find plant by sentence. * * @param sentence sentence to find plant in title or description. - * */ + */ operator fun invoke(sentence: String): Flow>> } diff --git a/domain/src/main/java/com/ujizin/leafy/domain/usecase/plant/find/FindPlantUseCaseImpl.kt b/domain/src/main/java/com/ujizin/leafy/domain/usecase/plant/find/FindPlantUseCaseImpl.kt index 31e73cc1..ff872e29 100644 --- a/domain/src/main/java/com/ujizin/leafy/domain/usecase/plant/find/FindPlantUseCaseImpl.kt +++ b/domain/src/main/java/com/ujizin/leafy/domain/usecase/plant/find/FindPlantUseCaseImpl.kt @@ -3,9 +3,7 @@ package com.ujizin.leafy.domain.usecase.plant.find import com.ujizin.leafy.domain.repository.PlantRepository import com.ujizin.leafy.domain.result.asResult -internal class FindPlantUseCaseImpl( - private val repository: PlantRepository, -) : FindPlantUseCase { +internal class FindPlantUseCaseImpl(private val repository: PlantRepository) : FindPlantUseCase { override fun invoke(sentence: String) = repository.findPlantBySentence(sentence).asResult() } diff --git a/domain/src/main/java/com/ujizin/leafy/domain/usecase/plant/load/LoadAllPlantUseCase.kt b/domain/src/main/java/com/ujizin/leafy/domain/usecase/plant/load/LoadAllPlantUseCase.kt index 8980479f..e0bbebeb 100644 --- a/domain/src/main/java/com/ujizin/leafy/domain/usecase/plant/load/LoadAllPlantUseCase.kt +++ b/domain/src/main/java/com/ujizin/leafy/domain/usecase/plant/load/LoadAllPlantUseCase.kt @@ -4,15 +4,13 @@ import com.ujizin.leafy.domain.model.Plant import com.ujizin.leafy.domain.result.Result import kotlinx.coroutines.flow.Flow -/** - * Use case to load all plant from repository. - * */ +/** Use case to load all plant from repository. */ interface LoadAllPlantUseCase { /** * Load all plant. * * @return list of all plant - * */ + */ operator fun invoke(): Flow>> } diff --git a/domain/src/main/java/com/ujizin/leafy/domain/usecase/plant/load/LoadAllPlantUseCaseImpl.kt b/domain/src/main/java/com/ujizin/leafy/domain/usecase/plant/load/LoadAllPlantUseCaseImpl.kt index 446d2b42..bba347a2 100644 --- a/domain/src/main/java/com/ujizin/leafy/domain/usecase/plant/load/LoadAllPlantUseCaseImpl.kt +++ b/domain/src/main/java/com/ujizin/leafy/domain/usecase/plant/load/LoadAllPlantUseCaseImpl.kt @@ -6,9 +6,8 @@ import com.ujizin.leafy.domain.result.Result import com.ujizin.leafy.domain.result.asResult import kotlinx.coroutines.flow.Flow -internal class LoadAllPlantUseCaseImpl( - private val repository: PlantRepository, -) : LoadAllPlantUseCase { +internal class LoadAllPlantUseCaseImpl(private val repository: PlantRepository) : + LoadAllPlantUseCase { override fun invoke(): Flow>> = repository.getPlants().asResult() } diff --git a/domain/src/main/java/com/ujizin/leafy/domain/usecase/plant/load/LoadDraftPlantUseCase.kt b/domain/src/main/java/com/ujizin/leafy/domain/usecase/plant/load/LoadDraftPlantUseCase.kt index e15f900d..c2724a3c 100644 --- a/domain/src/main/java/com/ujizin/leafy/domain/usecase/plant/load/LoadDraftPlantUseCase.kt +++ b/domain/src/main/java/com/ujizin/leafy/domain/usecase/plant/load/LoadDraftPlantUseCase.kt @@ -4,13 +4,9 @@ import com.ujizin.leafy.domain.model.Plant import com.ujizin.leafy.domain.result.Result import kotlinx.coroutines.flow.Flow -/** - * Use case to insert draft plant in the data source. - * */ +/** Use case to insert draft plant in the data source. */ interface LoadDraftPlantUseCase { - /** - * Get draft plant. - * */ + /** Get draft plant. */ operator fun invoke(): Flow> } diff --git a/domain/src/main/java/com/ujizin/leafy/domain/usecase/plant/load/LoadDraftPlantUseCaseImpl.kt b/domain/src/main/java/com/ujizin/leafy/domain/usecase/plant/load/LoadDraftPlantUseCaseImpl.kt index c9381ef5..0ea84fc9 100644 --- a/domain/src/main/java/com/ujizin/leafy/domain/usecase/plant/load/LoadDraftPlantUseCaseImpl.kt +++ b/domain/src/main/java/com/ujizin/leafy/domain/usecase/plant/load/LoadDraftPlantUseCaseImpl.kt @@ -6,9 +6,8 @@ import com.ujizin.leafy.domain.result.Result import com.ujizin.leafy.domain.result.asResult import kotlinx.coroutines.flow.Flow -internal class LoadDraftPlantUseCaseImpl( - private val repository: PlantRepository, -) : LoadDraftPlantUseCase { +internal class LoadDraftPlantUseCaseImpl(private val repository: PlantRepository) : + LoadDraftPlantUseCase { override fun invoke(): Flow> = repository.getDraftPlant().asResult() } diff --git a/domain/src/main/java/com/ujizin/leafy/domain/usecase/plant/load/LoadPlantUseCase.kt b/domain/src/main/java/com/ujizin/leafy/domain/usecase/plant/load/LoadPlantUseCase.kt index 8a8147e6..91da93fe 100644 --- a/domain/src/main/java/com/ujizin/leafy/domain/usecase/plant/load/LoadPlantUseCase.kt +++ b/domain/src/main/java/com/ujizin/leafy/domain/usecase/plant/load/LoadPlantUseCase.kt @@ -4,15 +4,13 @@ import com.ujizin.leafy.domain.model.Plant import com.ujizin.leafy.domain.result.Result import kotlinx.coroutines.flow.Flow -/** - * Load plant use case - * */ +/** Load plant use case */ interface LoadPlantUseCase { /** * Load plant by id. * * @param id the plant's id - * */ + */ operator fun invoke(id: Long): Flow> } diff --git a/domain/src/main/java/com/ujizin/leafy/domain/usecase/plant/update/UpdatePlant.kt b/domain/src/main/java/com/ujizin/leafy/domain/usecase/plant/update/UpdatePlant.kt index 695290dc..3b8dc645 100644 --- a/domain/src/main/java/com/ujizin/leafy/domain/usecase/plant/update/UpdatePlant.kt +++ b/domain/src/main/java/com/ujizin/leafy/domain/usecase/plant/update/UpdatePlant.kt @@ -3,15 +3,13 @@ package com.ujizin.leafy.domain.usecase.plant.update import com.ujizin.leafy.domain.model.Plant import kotlinx.coroutines.flow.Flow -/** - * Use case to update plant in the data source. - * */ +/** Use case to update plant in the data source. */ interface UpdatePlant { /** * Update a plant. * * @param plant plant to be updated - * */ + */ operator fun invoke(plant: Plant): Flow } diff --git a/domain/src/main/java/com/ujizin/leafy/domain/usecase/plant/update/UpdatePlantImpl.kt b/domain/src/main/java/com/ujizin/leafy/domain/usecase/plant/update/UpdatePlantImpl.kt index 69cece53..d2a7e615 100644 --- a/domain/src/main/java/com/ujizin/leafy/domain/usecase/plant/update/UpdatePlantImpl.kt +++ b/domain/src/main/java/com/ujizin/leafy/domain/usecase/plant/update/UpdatePlantImpl.kt @@ -4,9 +4,7 @@ import com.ujizin.leafy.domain.model.Plant import com.ujizin.leafy.domain.repository.PlantRepository import kotlinx.coroutines.flow.Flow -internal class UpdatePlantImpl( - private val plantRepository: PlantRepository, -) : UpdatePlant { +internal class UpdatePlantImpl(private val plantRepository: PlantRepository) : UpdatePlant { override fun invoke(plant: Plant): Flow = plantRepository.updatePlant(plant) } diff --git a/domain/src/main/java/com/ujizin/leafy/domain/usecase/ringtone/RingtoneModule.kt b/domain/src/main/java/com/ujizin/leafy/domain/usecase/ringtone/RingtoneModule.kt index 1904788d..5cfaa42e 100644 --- a/domain/src/main/java/com/ujizin/leafy/domain/usecase/ringtone/RingtoneModule.kt +++ b/domain/src/main/java/com/ujizin/leafy/domain/usecase/ringtone/RingtoneModule.kt @@ -15,7 +15,6 @@ object RingtoneModule { @Provides @Singleton - fun provideLoadRingtones( - repository: RingtoneRepository, - ): LoadRingtonesUseCase = LoadRingtonesUseCaseImpl(repository) + fun provideLoadRingtones(repository: RingtoneRepository): LoadRingtonesUseCase = + LoadRingtonesUseCaseImpl(repository) } diff --git a/domain/src/main/java/com/ujizin/leafy/domain/usecase/ringtone/load/LoadRingtonesUseCase.kt b/domain/src/main/java/com/ujizin/leafy/domain/usecase/ringtone/load/LoadRingtonesUseCase.kt index af81923e..fe76d6fd 100644 --- a/domain/src/main/java/com/ujizin/leafy/domain/usecase/ringtone/load/LoadRingtonesUseCase.kt +++ b/domain/src/main/java/com/ujizin/leafy/domain/usecase/ringtone/load/LoadRingtonesUseCase.kt @@ -3,9 +3,7 @@ package com.ujizin.leafy.domain.usecase.ringtone.load import com.ujizin.leafy.domain.model.Ringtone import kotlinx.coroutines.flow.Flow -/** - * Get all ringtones from android system source. - * */ +/** Get all ringtones from android system source. */ interface LoadRingtonesUseCase { operator fun invoke(): Flow> diff --git a/domain/src/main/java/com/ujizin/leafy/domain/usecase/ringtone/load/LoadRingtonesUseCaseImpl.kt b/domain/src/main/java/com/ujizin/leafy/domain/usecase/ringtone/load/LoadRingtonesUseCaseImpl.kt index 21fa7534..cd071bce 100644 --- a/domain/src/main/java/com/ujizin/leafy/domain/usecase/ringtone/load/LoadRingtonesUseCaseImpl.kt +++ b/domain/src/main/java/com/ujizin/leafy/domain/usecase/ringtone/load/LoadRingtonesUseCaseImpl.kt @@ -4,9 +4,8 @@ import com.ujizin.leafy.domain.model.Ringtone import com.ujizin.leafy.domain.repository.RingtoneRepository import kotlinx.coroutines.flow.Flow -internal class LoadRingtonesUseCaseImpl( - private val ringtoneRepository: RingtoneRepository, -) : LoadRingtonesUseCase { +internal class LoadRingtonesUseCaseImpl(private val ringtoneRepository: RingtoneRepository) : + LoadRingtonesUseCase { override fun invoke(): Flow> = ringtoneRepository.getRingtones() } diff --git a/domain/src/main/java/com/ujizin/leafy/domain/usecase/user/UserModule.kt b/domain/src/main/java/com/ujizin/leafy/domain/usecase/user/UserModule.kt index d32e3a8a..4e7d3c5c 100644 --- a/domain/src/main/java/com/ujizin/leafy/domain/usecase/user/UserModule.kt +++ b/domain/src/main/java/com/ujizin/leafy/domain/usecase/user/UserModule.kt @@ -17,13 +17,11 @@ object UserModule { @Provides @Singleton - fun provideLoadUser( - repository: UserRepository, - ): LoadUserUseCase = LoadUserUseCaseImpl(repository) + fun provideLoadUser(repository: UserRepository): LoadUserUseCase = + LoadUserUseCaseImpl(repository) @Provides @Singleton - fun provideUpdateUser( - repository: UserRepository, - ): UpdateUserUseCase = UpdateUserUseCaseImpl(repository) + fun provideUpdateUser(repository: UserRepository): UpdateUserUseCase = + UpdateUserUseCaseImpl(repository) } diff --git a/domain/src/main/java/com/ujizin/leafy/domain/usecase/user/load/LoadUserUseCase.kt b/domain/src/main/java/com/ujizin/leafy/domain/usecase/user/load/LoadUserUseCase.kt index d3c8eff8..f8d66283 100644 --- a/domain/src/main/java/com/ujizin/leafy/domain/usecase/user/load/LoadUserUseCase.kt +++ b/domain/src/main/java/com/ujizin/leafy/domain/usecase/user/load/LoadUserUseCase.kt @@ -4,15 +4,13 @@ import com.ujizin.leafy.domain.model.User import com.ujizin.leafy.domain.result.Result import kotlinx.coroutines.flow.Flow -/** - * Use case to load user in the data source. - * */ +/** Use case to load user in the data source. */ interface LoadUserUseCase { /** - * Load an user. + * Load an user. * - * @return an user - * */ + * @return an user + */ operator fun invoke(): Flow> } diff --git a/domain/src/main/java/com/ujizin/leafy/domain/usecase/user/update/UpdateUserUseCase.kt b/domain/src/main/java/com/ujizin/leafy/domain/usecase/user/update/UpdateUserUseCase.kt index 5a9a3faf..2c5a2b30 100644 --- a/domain/src/main/java/com/ujizin/leafy/domain/usecase/user/update/UpdateUserUseCase.kt +++ b/domain/src/main/java/com/ujizin/leafy/domain/usecase/user/update/UpdateUserUseCase.kt @@ -3,15 +3,13 @@ package com.ujizin.leafy.domain.usecase.user.update import com.ujizin.leafy.domain.model.User import kotlinx.coroutines.flow.Flow -/** - * Use case to update user in the data source. - * */ +/** Use case to update user in the data source. */ interface UpdateUserUseCase { /** - * Update an user. + * Update an user. * - * @return an user - * */ + * @return an user + */ operator fun invoke(user: User): Flow } diff --git a/domain/src/main/java/com/ujizin/leafy/domain/usecase/user/update/UpdateUserUseCaseImpl.kt b/domain/src/main/java/com/ujizin/leafy/domain/usecase/user/update/UpdateUserUseCaseImpl.kt index ec069a5c..ec190a68 100644 --- a/domain/src/main/java/com/ujizin/leafy/domain/usecase/user/update/UpdateUserUseCaseImpl.kt +++ b/domain/src/main/java/com/ujizin/leafy/domain/usecase/user/update/UpdateUserUseCaseImpl.kt @@ -3,9 +3,8 @@ package com.ujizin.leafy.domain.usecase.user.update import com.ujizin.leafy.domain.model.User import com.ujizin.leafy.domain.repository.UserRepository -internal class UpdateUserUseCaseImpl( - private val userRepository: UserRepository, -) : UpdateUserUseCase { +internal class UpdateUserUseCaseImpl(private val userRepository: UserRepository) : + UpdateUserUseCase { override fun invoke(user: User) = userRepository.updateUser(user) } diff --git a/domain/src/test/java/com/ujizin/leafy/domain/AlarmUseCaseTest.kt b/domain/src/test/java/com/ujizin/leafy/domain/AlarmUseCaseTest.kt index c5b55404..daba37af 100644 --- a/domain/src/test/java/com/ujizin/leafy/domain/AlarmUseCaseTest.kt +++ b/domain/src/test/java/com/ujizin/leafy/domain/AlarmUseCaseTest.kt @@ -28,11 +28,9 @@ import org.junit.Test class AlarmUseCaseTest { - @get:Rule - var mainCoroutineRule = TestDispatcherRule() + @get:Rule var mainCoroutineRule = TestDispatcherRule() - @MockK - private lateinit var alarmRepository: AlarmRepository + @MockK private lateinit var alarmRepository: AlarmRepository private lateinit var loadAlarmUseCase: LoadAlarmUseCase private lateinit var loadAlarmsUseCase: LoadAlarmsUseCase @@ -129,8 +127,7 @@ class AlarmUseCaseTest { } companion object { - private val alarmList = List(10) { - Alarm(it.toLong(), it.toLong(), "ring", it, true, it, listOf()) - } + private val alarmList = + List(10) { Alarm(it.toLong(), it.toLong(), "ring", it, true, it, listOf()) } } } diff --git a/domain/src/test/java/com/ujizin/leafy/domain/PlantUseCaseTest.kt b/domain/src/test/java/com/ujizin/leafy/domain/PlantUseCaseTest.kt index 57f614bf..026fc897 100644 --- a/domain/src/test/java/com/ujizin/leafy/domain/PlantUseCaseTest.kt +++ b/domain/src/test/java/com/ujizin/leafy/domain/PlantUseCaseTest.kt @@ -27,14 +27,11 @@ import org.junit.Test @ExperimentalCoroutinesApi class PlantUseCaseTest { - @get:Rule - val mainDispatcherRule = TestDispatcherRule() + @get:Rule val mainDispatcherRule = TestDispatcherRule() - @MockK - private lateinit var plantRepository: PlantRepository + @MockK private lateinit var plantRepository: PlantRepository - @MockK - private lateinit var fakePlant: Plant + @MockK private lateinit var fakePlant: Plant private lateinit var addPlantUseCase: AddPlantUseCase @@ -66,11 +63,12 @@ class PlantUseCaseTest { @Test fun `when load plant then expect return plants on repository`() = runTest { - val expectedPlants = listOf( - Plant(id = 1, "", "", "", false), - Plant(id = 2, "", "", "", false), - Plant(id = 3, "", "", "", false), - ) + val expectedPlants = + listOf( + Plant(id = 1, "", "", "", false), + Plant(id = 2, "", "", "", false), + Plant(id = 3, "", "", "", false), + ) every { plantRepository.getPlants() } returns flowOf(expectedPlants) @@ -85,17 +83,13 @@ class PlantUseCaseTest { fun `when update plant then expect call update plants on repository`() = runTest { every { plantRepository.updatePlant(fakePlant) } returns flowOf(Unit) - updatePlantUseCase(fakePlant).collect { - verify { plantRepository.updatePlant(fakePlant) } - } + updatePlantUseCase(fakePlant).collect { verify { plantRepository.updatePlant(fakePlant) } } } @Test fun `when delete plant then expect call delete plants on repository`() = runTest { every { plantRepository.deletePlant(fakePlant) } returns flowOf(Unit) - deletePlantUseCase(fakePlant).collect { - verify { plantRepository.deletePlant(fakePlant) } - } + deletePlantUseCase(fakePlant).collect { verify { plantRepository.deletePlant(fakePlant) } } } } diff --git a/domain/src/test/java/com/ujizin/leafy/domain/RingtoneUseCaseTest.kt b/domain/src/test/java/com/ujizin/leafy/domain/RingtoneUseCaseTest.kt index d2a3aa42..5809422a 100644 --- a/domain/src/test/java/com/ujizin/leafy/domain/RingtoneUseCaseTest.kt +++ b/domain/src/test/java/com/ujizin/leafy/domain/RingtoneUseCaseTest.kt @@ -18,11 +18,9 @@ import org.junit.Test class RingtoneUseCaseTest { - @get:Rule - var mainDispatcherRule = TestDispatcherRule() + @get:Rule var mainDispatcherRule = TestDispatcherRule() - @MockK - private lateinit var ringtoneRepository: RingtoneRepository + @MockK private lateinit var ringtoneRepository: RingtoneRepository private lateinit var loadRingtonesUseCase: LoadRingtonesUseCase @@ -46,8 +44,6 @@ class RingtoneUseCaseTest { } companion object { - private val ringtones = List(10) { - Ringtone("$it", "title-$it", "uriContent-$it") - } + private val ringtones = List(10) { Ringtone("$it", "title-$it", "uriContent-$it") } } } diff --git a/domain/src/test/java/com/ujizin/leafy/domain/UserUseCaseTest.kt b/domain/src/test/java/com/ujizin/leafy/domain/UserUseCaseTest.kt index 1c245871..d1af1e76 100644 --- a/domain/src/test/java/com/ujizin/leafy/domain/UserUseCaseTest.kt +++ b/domain/src/test/java/com/ujizin/leafy/domain/UserUseCaseTest.kt @@ -24,11 +24,9 @@ import org.junit.Test class UserUseCaseTest { - @get:Rule - var mainDispatcherRule = TestDispatcherRule() + @get:Rule var mainDispatcherRule = TestDispatcherRule() - @MockK - lateinit var userRepository: UserRepository + @MockK lateinit var userRepository: UserRepository private lateinit var loadUserUseCase: LoadUserUseCase @@ -67,9 +65,7 @@ class UserUseCaseTest { } companion object { - private val user = User( - nickname = "nickname", - settings = User.Settings(Theme.Dark, Language.EN, true), - ) + private val user = + User(nickname = "nickname", settings = User.Settings(Theme.Dark, Language.EN, true)) } } diff --git a/features/about/build.gradle.kts b/features/about/build.gradle.kts index 8ac557d4..b792781f 100644 --- a/features/about/build.gradle.kts +++ b/features/about/build.gradle.kts @@ -1,17 +1,3 @@ -plugins { - alias(libs.plugins.android.library) - alias(libs.plugins.kotlin.android) -} +plugins { id("com.ujizin.android-feature") } -apply(from = "$rootDir/config-compose.gradle") -apply(from = "$rootDir/config-android.gradle") - -android { - namespace = "com.ujizin.leafy.features.about" -} - -dependencies { - implementation(projects.core.navigation) - implementation(projects.core.ui) - implementation(projects.core.themes) -} +android { namespace = "com.ujizin.leafy.features.about" } diff --git a/features/about/src/main/java/com/ujizin/leafy/about/About.kt b/features/about/src/main/java/com/ujizin/leafy/about/About.kt index cf059f8a..2b3f99a7 100644 --- a/features/about/src/main/java/com/ujizin/leafy/about/About.kt +++ b/features/about/src/main/java/com/ujizin/leafy/about/About.kt @@ -29,13 +29,13 @@ import androidx.compose.ui.res.stringResource import androidx.compose.ui.unit.Dp import androidx.compose.ui.unit.dp import androidx.compose.ui.unit.sp +import com.ujizin.leafy.core.components.R as CR import com.ujizin.leafy.core.ui.components.animated.AnimatedButtonIcon import com.ujizin.leafy.core.ui.components.button.Button import com.ujizin.leafy.core.ui.components.image.Icons import com.ujizin.leafy.core.ui.extensions.OnClick import com.ujizin.leafy.core.ui.extensions.capitalize import com.ujizin.leafy.features.about.R -import com.ujizin.leafy.core.components.R as CR @OptIn(ExperimentalMaterial3Api::class) @Composable @@ -65,10 +65,7 @@ fun AboutRoute(onBackPressed: OnClick) { }, ) { AboutContent( - modifier = Modifier - .padding(it) - .fillMaxSize() - .verticalScroll(rememberScrollState()), + modifier = Modifier.padding(it).fillMaxSize().verticalScroll(rememberScrollState()) ) } } @@ -78,9 +75,8 @@ private fun AboutContent(modifier: Modifier = Modifier) { Column(modifier) { val context = LocalContext.current Image( - modifier = Modifier - .background(MaterialTheme.colorScheme.onSecondaryContainer) - .aspectRatio(2F), + modifier = + Modifier.background(MaterialTheme.colorScheme.onSecondaryContainer).aspectRatio(2F), contentScale = ContentScale.Fit, painter = painterResource(id = CR.drawable.ic_launcher_foreground), contentDescription = null, @@ -90,9 +86,7 @@ private fun AboutContent(modifier: Modifier = Modifier) { Spacer(modifier = Modifier.weight(1F)) Button( - modifier = Modifier - .fillMaxWidth() - .padding(20.dp), + modifier = Modifier.fillMaxWidth().padding(20.dp), text = stringResource(id = R.string.about_button), onClick = context::openProject, ) @@ -115,8 +109,7 @@ private fun AboutSection(modifier: Modifier = Modifier) { } private fun Context.openProject() { - val intent = Intent(Intent.ACTION_VIEW).apply { - data = Uri.parse(getString(R.string.about_project_url)) - } + val intent = + Intent(Intent.ACTION_VIEW).apply { data = Uri.parse(getString(R.string.about_project_url)) } startActivity(intent) } diff --git a/features/about/src/main/java/com/ujizin/leafy/about/AboutGraph.kt b/features/about/src/main/java/com/ujizin/leafy/about/AboutGraph.kt index b9fefb99..82bd88d4 100644 --- a/features/about/src/main/java/com/ujizin/leafy/about/AboutGraph.kt +++ b/features/about/src/main/java/com/ujizin/leafy/about/AboutGraph.kt @@ -7,9 +7,7 @@ import com.ujizin.leafy.core.ui.extensions.OnClick import com.ujizin.leafy.core.ui.extensions.fullSlideInVertically import com.ujizin.leafy.core.ui.extensions.fullSlideOutVertically -fun NavGraphBuilder.aboutGraph( - onBackPressed: OnClick, -) { +fun NavGraphBuilder.aboutGraph(onBackPressed: OnClick) { composable( enterTransition = { fullSlideInVertically() }, exitTransition = { fullSlideOutVertically() }, diff --git a/features/alarm/build.gradle.kts b/features/alarm/build.gradle.kts index 25e05675..bc3ca2d9 100644 --- a/features/alarm/build.gradle.kts +++ b/features/alarm/build.gradle.kts @@ -1,26 +1,3 @@ -plugins { - alias(libs.plugins.android.library) - alias(libs.plugins.kotlin.android) -} +plugins { id("com.ujizin.android-feature") } -apply(from = "$rootDir/config-compose.gradle") -apply(from = "$rootDir/config-android.gradle") - -android { - namespace = "com.ujizin.leafy.features.alarm" - - testOptions { - unitTests.isReturnDefaultValues = true - } -} - -dependencies { - implementation(projects.core.navigation) - implementation(projects.core.ui) - implementation(projects.core.themes) - implementation(projects.domain) - - testImplementation(projects.core.test) - testImplementation(libs.bundles.test) - testImplementation(libs.coroutines.test) -} +android { namespace = "com.ujizin.leafy.features.alarm" } diff --git a/features/alarm/src/main/java/com/ujizin/leafy/alarm/AlarmModule.kt b/features/alarm/src/main/java/com/ujizin/leafy/alarm/AlarmModule.kt index cf54ab9e..4c348303 100644 --- a/features/alarm/src/main/java/com/ujizin/leafy/alarm/AlarmModule.kt +++ b/features/alarm/src/main/java/com/ujizin/leafy/alarm/AlarmModule.kt @@ -21,9 +21,8 @@ object AlarmModule { @Provides @Singleton - fun provideAlarmScheduler( - @ApplicationContext context: Context, - ): AlarmScheduler = AlarmSchedulerImpl(context) + fun provideAlarmScheduler(@ApplicationContext context: Context): AlarmScheduler = + AlarmSchedulerImpl(context) @Provides @Singleton @@ -35,7 +34,6 @@ object AlarmModule { @Provides @Singleton - fun provideAlarmNotificator( - @ApplicationContext context: Context, - ): AlarmNotificator = AlarmNotificatorImpl(context) + fun provideAlarmNotificator(@ApplicationContext context: Context): AlarmNotificator = + AlarmNotificatorImpl(context) } diff --git a/features/alarm/src/main/java/com/ujizin/leafy/alarm/AlarmService.kt b/features/alarm/src/main/java/com/ujizin/leafy/alarm/AlarmService.kt index 90e14989..ab4504ac 100644 --- a/features/alarm/src/main/java/com/ujizin/leafy/alarm/AlarmService.kt +++ b/features/alarm/src/main/java/com/ujizin/leafy/alarm/AlarmService.kt @@ -17,6 +17,7 @@ import com.ujizin.leafy.alarm.extensions.getAlarmIntent import com.ujizin.leafy.alarm.extensions.orDefaultRingtone import com.ujizin.leafy.alarm.notificator.AlarmNotificator import com.ujizin.leafy.alarm.receiver.StopPlantServiceActivity +import com.ujizin.leafy.core.components.R as CR import com.ujizin.leafy.core.navigation.Destination import com.ujizin.leafy.core.ui.props.RequestCode import com.ujizin.leafy.features.alarm.R @@ -24,30 +25,28 @@ import dagger.hilt.android.AndroidEntryPoint import java.io.IOException import javax.inject.Inject import kotlin.time.Duration.Companion.minutes -import com.ujizin.leafy.core.components.R as CR @AndroidEntryPoint class AlarmService : Service() { private var mediaPlayer: MediaPlayer? = null - @Inject - lateinit var alarmNotificator: AlarmNotificator + @Inject lateinit var alarmNotificator: AlarmNotificator - private val Intent.plantId get() = getLongExtra(PLANT_ID, -1) + private val Intent.plantId + get() = getLongExtra(PLANT_ID, -1) private val Intent.ringtoneUri get() = getStringExtra(RINGTONE_URI_STRINGIFY_ARG)?.let(Uri::parse).orDefaultRingtone() - private val countDownTimer = object : CountDownTimer( - TIME_OUT_IN_MILLISECONDS, - TICK_IN_MILLISECONDS, - ) { - override fun onTick(millisUntilFinished: Long) = Unit /* no-op */ - override fun onFinish() { - mediaPlayer?.pause() + private val countDownTimer = + object : CountDownTimer(TIME_OUT_IN_MILLISECONDS, TICK_IN_MILLISECONDS) { + override fun onTick(millisUntilFinished: Long) = Unit /* no-op */ + + override fun onFinish() { + mediaPlayer?.pause() + } } - } private val wakeLock: PowerManager.WakeLock by lazy { (getSystemService(POWER_SERVICE) as PowerManager).run { @@ -70,10 +69,11 @@ class AlarmService : Service() { } @Suppress("DEPRECATION") - private fun stopForeground() = when { - Build.VERSION.SDK_INT >= Build.VERSION_CODES.N -> stopForeground(STOP_FOREGROUND_REMOVE) - else -> stopForeground(true) - } + private fun stopForeground() = + when { + Build.VERSION.SDK_INT >= Build.VERSION_CODES.N -> stopForeground(STOP_FOREGROUND_REMOVE) + else -> stopForeground(true) + } private fun startAlarm(intent: Intent) { wakeLock.acquire(1.minutes.inWholeMilliseconds) @@ -92,51 +92,49 @@ class AlarmService : Service() { title = title, description = description, contentIntent = contentIntent, - notificationActions = listOf( - NotificationCompat.Action(0, getString(R.string.stop), stopIntent), - ), + notificationActions = + listOf(NotificationCompat.Action(0, getString(R.string.stop), stopIntent)), ) } - private fun getAlarmPendingIntent(action: String) = PendingIntent.getService( - this, - RequestCode.ALARM, - getAlarmIntent(action), - PendingIntent.FLAG_IMMUTABLE, - ) + private fun getAlarmPendingIntent(action: String) = + PendingIntent.getService( + this, + RequestCode.ALARM, + getAlarmIntent(action), + PendingIntent.FLAG_IMMUTABLE, + ) private fun Uri.play() { try { - val audioAttributes = AudioAttributes.Builder() - .setUsage(AudioAttributes.USAGE_ALARM) - .setContentType(AudioAttributes.CONTENT_TYPE_SONIFICATION) - .build() - - mediaPlayer = MediaPlayer().apply { - setDataSource(this@AlarmService, this@play) - setAudioAttributes(audioAttributes) - prepareAsync() - setOnPreparedListener { start() } - } - } catch (_: IOException) { - } + val audioAttributes = + AudioAttributes.Builder() + .setUsage(AudioAttributes.USAGE_ALARM) + .setContentType(AudioAttributes.CONTENT_TYPE_SONIFICATION) + .build() + + mediaPlayer = + MediaPlayer().apply { + setDataSource(this@AlarmService, this@play) + setAudioAttributes(audioAttributes) + prepareAsync() + setOnPreparedListener { start() } + } + } catch (_: IOException) {} } - private fun getPlantPendingIntent( - plantId: Long, - ) = TaskStackBuilder.create(this).run { - val deeplinkIntent = Intent( - Intent.ACTION_VIEW, - Destination.PlantDetails.createDeeplink(plantId), - ).apply { - putExtra(ALARM_SERVICE_ARG, true) - flags = Intent.FLAG_ACTIVITY_NEW_TASK or Intent.FLAG_ACTIVITY_CLEAR_TASK + private fun getPlantPendingIntent(plantId: Long) = + TaskStackBuilder.create(this).run { + val deeplinkIntent = + Intent(Intent.ACTION_VIEW, Destination.PlantDetails.createDeeplink(plantId)).apply { + putExtra(ALARM_SERVICE_ARG, true) + flags = Intent.FLAG_ACTIVITY_NEW_TASK or Intent.FLAG_ACTIVITY_CLEAR_TASK + } + val stopService = StopPlantServiceActivity.getIntent(this@AlarmService) + addNextIntentWithParentStack(deeplinkIntent) + addNextIntent(stopService) + getPendingIntent(0, PendingIntent.FLAG_IMMUTABLE) } - val stopService = StopPlantServiceActivity.getIntent(this@AlarmService) - addNextIntentWithParentStack(deeplinkIntent) - addNextIntent(stopService) - getPendingIntent(0, PendingIntent.FLAG_IMMUTABLE) - } override fun onDestroy() { wakeLock.release() diff --git a/features/alarm/src/main/java/com/ujizin/leafy/alarm/extensions/AlarmExtensions.kt b/features/alarm/src/main/java/com/ujizin/leafy/alarm/extensions/AlarmExtensions.kt index fd7060af..0179063e 100644 --- a/features/alarm/src/main/java/com/ujizin/leafy/alarm/extensions/AlarmExtensions.kt +++ b/features/alarm/src/main/java/com/ujizin/leafy/alarm/extensions/AlarmExtensions.kt @@ -8,39 +8,28 @@ import android.os.Build import android.provider.Settings import com.ujizin.leafy.alarm.AlarmService -/** - * Get alarm manager instance from context - * */ -val Context.alarmManager get() = getSystemService(Context.ALARM_SERVICE) as AlarmManager +/** Get alarm manager instance from context */ +val Context.alarmManager + get() = getSystemService(Context.ALARM_SERVICE) as AlarmManager -/** - * Start alarm permission intent if there's no alarm permission - * */ +/** Start alarm permission intent if there's no alarm permission */ @SuppressLint("InlinedApi") fun Context.startAlarmPermission() { if (alarmManager.hasAlarmPermission) return - val intent = Intent().apply { - action = Settings.ACTION_REQUEST_SCHEDULE_EXACT_ALARM - } + val intent = Intent().apply { action = Settings.ACTION_REQUEST_SCHEDULE_EXACT_ALARM } startActivity(intent) } -/** - * Check if has permission in schedule alarms. - * */ +/** Check if has permission in schedule alarms. */ val AlarmManager.hasAlarmPermission - get() = when { - Build.VERSION.SDK_INT >= Build.VERSION_CODES.S -> canScheduleExactAlarms() - else -> true - } + get() = + when { + Build.VERSION.SDK_INT >= Build.VERSION_CODES.S -> canScheduleExactAlarms() + else -> true + } -/** - * Get alarm service intent - * */ -internal fun Context.getAlarmIntent( - action: String? = null, -) = Intent(this, AlarmService::class.java).apply { - this.action = action -} +/** Get alarm service intent */ +internal fun Context.getAlarmIntent(action: String? = null) = + Intent(this, AlarmService::class.java).apply { this.action = action } diff --git a/features/alarm/src/main/java/com/ujizin/leafy/alarm/extensions/RingtoneExtensions.kt b/features/alarm/src/main/java/com/ujizin/leafy/alarm/extensions/RingtoneExtensions.kt index e69a7abc..587d81a0 100644 --- a/features/alarm/src/main/java/com/ujizin/leafy/alarm/extensions/RingtoneExtensions.kt +++ b/features/alarm/src/main/java/com/ujizin/leafy/alarm/extensions/RingtoneExtensions.kt @@ -5,10 +5,12 @@ import android.media.RingtoneManager import com.ujizin.leafy.core.ui.components.selector.ModalValue import com.ujizin.leafy.domain.model.Ringtone -fun ModalValue?.orDefault(context: Context) = this ?: run { - val default = getDefaultRingtone(context) - ModalValue(default.title, default) -} +fun ModalValue?.orDefault(context: Context) = + this + ?: run { + val default = getDefaultRingtone(context) + ModalValue(default.title, default) + } fun getDefaultRingtone(context: Context): Ringtone { val uri = RingtoneManager.getDefaultUri(RingtoneManager.TYPE_RINGTONE) diff --git a/features/alarm/src/main/java/com/ujizin/leafy/alarm/model/RepeatMode.kt b/features/alarm/src/main/java/com/ujizin/leafy/alarm/model/RepeatMode.kt index 2f5db783..0d251dc4 100644 --- a/features/alarm/src/main/java/com/ujizin/leafy/alarm/model/RepeatMode.kt +++ b/features/alarm/src/main/java/com/ujizin/leafy/alarm/model/RepeatMode.kt @@ -4,26 +4,21 @@ import androidx.annotation.StringRes import com.ujizin.leafy.domain.model.WeekDay import com.ujizin.leafy.features.alarm.R -sealed class RepeatMode( - @StringRes val display: Int, - val weekDays: List, -) { +sealed class RepeatMode(@StringRes val display: Int, val weekDays: List) { data object Daily : RepeatMode(R.string.daily, WeekDay.entries) - data object MonToFriday : RepeatMode( - R.string.mon_to_friday, - WeekDay.entries.filter { it != WeekDay.Saturday && it != WeekDay.Sunday }, - ) + data object MonToFriday : + RepeatMode( + R.string.mon_to_friday, + WeekDay.entries.filter { it != WeekDay.Saturday && it != WeekDay.Sunday }, + ) data class Custom(val customWeekDays: List) : RepeatMode(R.string.custom, customWeekDays) companion object { - fun getValues(customWeekDays: List = emptyList()): List = listOf( - Daily, - MonToFriday, - Custom(customWeekDays), - ) + fun getValues(customWeekDays: List = emptyList()): List = + listOf(Daily, MonToFriday, Custom(customWeekDays)) } } diff --git a/features/alarm/src/main/java/com/ujizin/leafy/alarm/notificator/AlarmNotificator.kt b/features/alarm/src/main/java/com/ujizin/leafy/alarm/notificator/AlarmNotificator.kt index a4bea9dd..cac2c38f 100644 --- a/features/alarm/src/main/java/com/ujizin/leafy/alarm/notificator/AlarmNotificator.kt +++ b/features/alarm/src/main/java/com/ujizin/leafy/alarm/notificator/AlarmNotificator.kt @@ -4,9 +4,7 @@ import android.app.Notification import android.app.PendingIntent import androidx.core.app.NotificationCompat -/** - * Create alarm notification for Android system. - * */ +/** Create alarm notification for Android system. */ interface AlarmNotificator { fun createChannel() diff --git a/features/alarm/src/main/java/com/ujizin/leafy/alarm/notificator/AlarmNotificatorImpl.kt b/features/alarm/src/main/java/com/ujizin/leafy/alarm/notificator/AlarmNotificatorImpl.kt index 88a16b2d..70886543 100644 --- a/features/alarm/src/main/java/com/ujizin/leafy/alarm/notificator/AlarmNotificatorImpl.kt +++ b/features/alarm/src/main/java/com/ujizin/leafy/alarm/notificator/AlarmNotificatorImpl.kt @@ -21,19 +21,20 @@ internal class AlarmNotificatorImpl(private val context: Context) : AlarmNotific fullScreenIntent: PendingIntent?, contentIntent: PendingIntent?, notificationActions: List, - ) = NotificationCompat.Builder(context, CHANNEL_ID) - .setSmallIcon(R.drawable.ic_notification_monochrome) - .setContentTitle(title) - .setContentText(description) - .setVibrate(vibrateValues) - .setOngoing(true) - .setAutoCancel(false) - .setPriority(NotificationCompat.PRIORITY_MAX) - .setCategory(NotificationCompat.CATEGORY_ALARM) - .setFullScreenIntent(fullScreenIntent, true) - .setContentIntent(contentIntent) - .apply { notificationActions.forEach(::addAction) } - .build() + ) = + NotificationCompat.Builder(context, CHANNEL_ID) + .setSmallIcon(R.drawable.ic_notification_monochrome) + .setContentTitle(title) + .setContentText(description) + .setVibrate(vibrateValues) + .setOngoing(true) + .setAutoCancel(false) + .setPriority(NotificationCompat.PRIORITY_MAX) + .setCategory(NotificationCompat.CATEGORY_ALARM) + .setFullScreenIntent(fullScreenIntent, true) + .setContentIntent(contentIntent) + .apply { notificationActions.forEach(::addAction) } + .build() override fun cancelNotification(notificationId: Int) { notificationManagerCompat.cancel(notificationId) @@ -44,11 +45,8 @@ internal class AlarmNotificatorImpl(private val context: Context) : AlarmNotific return } - val notificationChannel = NotificationChannel( - CHANNEL_ID, - CHANNEL_NAME, - NotificationManager.IMPORTANCE_HIGH, - ) + val notificationChannel = + NotificationChannel(CHANNEL_ID, CHANNEL_NAME, NotificationManager.IMPORTANCE_HIGH) notificationManagerCompat.createNotificationChannel(notificationChannel) } diff --git a/features/alarm/src/main/java/com/ujizin/leafy/alarm/receiver/AlarmReceiver.kt b/features/alarm/src/main/java/com/ujizin/leafy/alarm/receiver/AlarmReceiver.kt index 14f904ff..738e79f2 100644 --- a/features/alarm/src/main/java/com/ujizin/leafy/alarm/receiver/AlarmReceiver.kt +++ b/features/alarm/src/main/java/com/ujizin/leafy/alarm/receiver/AlarmReceiver.kt @@ -15,62 +15,57 @@ import com.ujizin.leafy.domain.model.Plant import com.ujizin.leafy.domain.result.mapResult import com.ujizin.leafy.domain.usecase.alarm.load.LoadAlarmsUseCase import dagger.hilt.android.AndroidEntryPoint +import javax.inject.Inject import kotlinx.coroutines.DelicateCoroutinesApi import kotlinx.coroutines.GlobalScope import kotlinx.coroutines.flow.emptyFlow import kotlinx.coroutines.flow.launchIn import kotlinx.coroutines.flow.onEach -import javax.inject.Inject @AndroidEntryPoint class AlarmReceiver : BroadcastReceiver() { - @Inject - lateinit var schedulePlantAlarm: SchedulePlantAlarmUseCase + @Inject lateinit var schedulePlantAlarm: SchedulePlantAlarmUseCase - @Inject - lateinit var loadAlarms: LoadAlarmsUseCase + @Inject lateinit var loadAlarms: LoadAlarmsUseCase - @Inject - lateinit var alarmScheduler: AlarmScheduler + @Inject lateinit var alarmScheduler: AlarmScheduler - private val Intent.alarmId get() = getLongExtra(ALARM_ID_EXTRA, -1) + private val Intent.alarmId + get() = getLongExtra(ALARM_ID_EXTRA, -1) - private val Intent.ringtoneStringify get() = getStringExtra(RINGTONE_CONTENT_EXTRA) + private val Intent.ringtoneStringify + get() = getStringExtra(RINGTONE_CONTENT_EXTRA) @OptIn(DelicateCoroutinesApi::class) override fun onReceive(context: Context, intent: Intent) { when (intent.action) { - SCHEDULE_ALARM_ACTION -> schedulePlantAlarm( - alarmId = intent.alarmId, - actualDay = currentDay + 1, - ).onEach { plant -> - context.ringPlantAlarm(intent, plant) - } + SCHEDULE_ALARM_ACTION -> + schedulePlantAlarm(alarmId = intent.alarmId, actualDay = currentDay + 1).onEach { + plant -> + context.ringPlantAlarm(intent, plant) + } Intent.ACTION_TIME_CHANGED, Intent.ACTION_BOOT_COMPLETED, - AlarmManager.ACTION_SCHEDULE_EXACT_ALARM_PERMISSION_STATE_CHANGED, - -> loadAlarms() - .mapResult() - .onEach { alarms -> alarms.forEach(alarmScheduler::scheduleAlarm) } + AlarmManager.ACTION_SCHEDULE_EXACT_ALARM_PERMISSION_STATE_CHANGED -> + loadAlarms().mapResult().onEach { alarms -> + alarms.forEach(alarmScheduler::scheduleAlarm) + } else -> emptyFlow() }.launchIn(GlobalScope) } - private fun Context.ringPlantAlarm(intent: Intent, plant: Plant) = startAlarmService( - serviceIntent = getAlarmServiceIntent(plant, intent.ringtoneStringify), - ) - - private fun Context.getAlarmServiceIntent( - plant: Plant, - ringtone: String?, - ) = getAlarmIntent().apply { - putExtra(AlarmService.PLANT_ID, plant.id) - putExtra(AlarmService.TITLE_ARG, getString(R.string.app_name)) - putExtra(AlarmService.DESCRIPTION_ARG, plant.title) - putExtra(AlarmService.RINGTONE_URI_STRINGIFY_ARG, ringtone) - } + private fun Context.ringPlantAlarm(intent: Intent, plant: Plant) = + startAlarmService(serviceIntent = getAlarmServiceIntent(plant, intent.ringtoneStringify)) + + private fun Context.getAlarmServiceIntent(plant: Plant, ringtone: String?) = + getAlarmIntent().apply { + putExtra(AlarmService.PLANT_ID, plant.id) + putExtra(AlarmService.TITLE_ARG, getString(R.string.app_name)) + putExtra(AlarmService.DESCRIPTION_ARG, plant.title) + putExtra(AlarmService.RINGTONE_URI_STRINGIFY_ARG, ringtone) + } private fun Context.startAlarmService(serviceIntent: Intent) { startService(serviceIntent) diff --git a/features/alarm/src/main/java/com/ujizin/leafy/alarm/scheduler/AlarmScheduler.kt b/features/alarm/src/main/java/com/ujizin/leafy/alarm/scheduler/AlarmScheduler.kt index 125dacce..690a9bcf 100644 --- a/features/alarm/src/main/java/com/ujizin/leafy/alarm/scheduler/AlarmScheduler.kt +++ b/features/alarm/src/main/java/com/ujizin/leafy/alarm/scheduler/AlarmScheduler.kt @@ -9,9 +9,7 @@ import com.ujizin.leafy.core.ui.extensions.getNearestDay import com.ujizin.leafy.domain.model.Alarm import com.ujizin.leafy.domain.model.WeekDay -/** - * Create alarm scheduler for Android Alarm Manager system. - * */ +/** Create alarm scheduler for Android Alarm Manager system. */ interface AlarmScheduler { /** @@ -24,7 +22,7 @@ interface AlarmScheduler { * @param ringtoneUri the alarm's ringtone uri * @param requestCode alarm's request code * @param bundle bundle for pending intent - * */ + */ fun scheduleAlarm( type: Int = AlarmManager.RTC_WAKEUP, dayOfWeek: Int, @@ -39,20 +37,21 @@ interface AlarmScheduler { * Cancel alarm scheduled on Android System. * * @param requestCode alarm's request code - * */ + */ fun cancelAlarm(requestCode: Int = 0) /** * Schedule alarm on Android System. * * @param alarm alarm to be scheduled. - * */ - fun scheduleAlarm(alarm: Alarm, day: WeekDay = currentDay) = scheduleAlarm( - dayOfWeek = alarm.weekDays.getNearestDay(alarm.hours, alarm.minutes, day).ordinal + 1, - hours = alarm.hours, - minutes = alarm.minutes, - ringtoneUri = alarm.ringtoneUriContent, - requestCode = alarm.id.toInt(), - bundle = bundleOf(AlarmReceiver.ALARM_ID_EXTRA to alarm.id), - ) + */ + fun scheduleAlarm(alarm: Alarm, day: WeekDay = currentDay) = + scheduleAlarm( + dayOfWeek = alarm.weekDays.getNearestDay(alarm.hours, alarm.minutes, day).ordinal + 1, + hours = alarm.hours, + minutes = alarm.minutes, + ringtoneUri = alarm.ringtoneUriContent, + requestCode = alarm.id.toInt(), + bundle = bundleOf(AlarmReceiver.ALARM_ID_EXTRA to alarm.id), + ) } diff --git a/features/alarm/src/main/java/com/ujizin/leafy/alarm/scheduler/AlarmSchedulerImpl.kt b/features/alarm/src/main/java/com/ujizin/leafy/alarm/scheduler/AlarmSchedulerImpl.kt index 52f03ac6..9157396a 100644 --- a/features/alarm/src/main/java/com/ujizin/leafy/alarm/scheduler/AlarmSchedulerImpl.kt +++ b/features/alarm/src/main/java/com/ujizin/leafy/alarm/scheduler/AlarmSchedulerImpl.kt @@ -34,7 +34,7 @@ internal class AlarmSchedulerImpl(private val context: Context) : AlarmScheduler * @param hours the alarm's hours * @param minutes the alarm's minutes * @param ringtoneUri the alarm's ringtone uri - * */ + */ private fun setAlarm( type: Int, dayOfWeek: Int, @@ -57,18 +57,15 @@ internal class AlarmSchedulerImpl(private val context: Context) : AlarmScheduler * * @param hours the timer's hours * @param minutes the timer's minutes - * */ - private fun getTimeInMillis( - dayOfWeek: Int, - hours: Int, - minutes: Int, - ): Long = with(Calendar.getInstance()) { - set(Calendar.HOUR_OF_DAY, hours) - set(Calendar.MINUTE, minutes) - setDay(dayOfWeek, hours, minutes) + */ + private fun getTimeInMillis(dayOfWeek: Int, hours: Int, minutes: Int): Long = + with(Calendar.getInstance()) { + set(Calendar.HOUR_OF_DAY, hours) + set(Calendar.MINUTE, minutes) + setDay(dayOfWeek, hours, minutes) - return@with timeInMillis - } + return@with timeInMillis + } private fun Calendar.setDay(dayOfWeek: Int, hours: Int, minutes: Int) { val currentDayOfWeek = get(Calendar.DAY_OF_WEEK) @@ -90,19 +87,20 @@ internal class AlarmSchedulerImpl(private val context: Context) : AlarmScheduler * Create pending intent for alarm * * @param ringtoneUri the alarm's ringtone - * */ + */ private fun createPendingIntent( ringtoneUri: Uri = Uri.EMPTY, requestCode: Int = 0, bundle: Bundle = Bundle.EMPTY, - ): PendingIntent = PendingIntent.getBroadcast( - context, - requestCode, - Intent(context, AlarmReceiver::class.java).apply { - action = AlarmReceiver.SCHEDULE_ALARM_ACTION - putExtra(AlarmReceiver.RINGTONE_CONTENT_EXTRA, ringtoneUri.toString()) - putExtras(bundle) - }, - PendingIntent.FLAG_IMMUTABLE or PendingIntent.FLAG_UPDATE_CURRENT, - ) + ): PendingIntent = + PendingIntent.getBroadcast( + context, + requestCode, + Intent(context, AlarmReceiver::class.java).apply { + action = AlarmReceiver.SCHEDULE_ALARM_ACTION + putExtra(AlarmReceiver.RINGTONE_CONTENT_EXTRA, ringtoneUri.toString()) + putExtras(bundle) + }, + PendingIntent.FLAG_IMMUTABLE or PendingIntent.FLAG_UPDATE_CURRENT, + ) } diff --git a/features/alarm/src/main/java/com/ujizin/leafy/alarm/ui/AlarmSection.kt b/features/alarm/src/main/java/com/ujizin/leafy/alarm/ui/AlarmSection.kt index bb96a72c..512d8c42 100644 --- a/features/alarm/src/main/java/com/ujizin/leafy/alarm/ui/AlarmSection.kt +++ b/features/alarm/src/main/java/com/ujizin/leafy/alarm/ui/AlarmSection.kt @@ -60,32 +60,29 @@ fun AlarmRoute( val ringtones by remember { derivedStateOf { - (uiState as? AlarmUiState.Initialized)?.ringtones.orEmpty() - .map { ModalValue(it.title, it) } + (uiState as? AlarmUiState.Initialized)?.ringtones.orEmpty().map { + ModalValue(it.title, it) + } } } - var ringtone by remember(ringtones) { - mutableStateOf(ringtones.firstOrNull().orDefault(context)) - } + var ringtone by + remember(ringtones) { mutableStateOf(ringtones.firstOrNull().orDefault(context)) } var repeatMode: ModalValue by remember { - mutableStateOf( - ModalValue(context.getString(RepeatMode.Daily.display), RepeatMode.Daily), - ) + mutableStateOf(ModalValue(context.getString(RepeatMode.Daily.display), RepeatMode.Daily)) } - val repeatValues = remember(repeatMode) { - RepeatMode.getValues(repeatMode.value.asCustom()?.customWeekDays.orEmpty()).map { - ModalValue(context.getString(it.display), it) + val repeatValues = + remember(repeatMode) { + RepeatMode.getValues(repeatMode.value.asCustom()?.customWeekDays.orEmpty()).map { + ModalValue(context.getString(it.display), it) + } } - } var hours by remember { mutableIntStateOf(0) } var minutes by remember { mutableIntStateOf(0) } LaunchedEffect(viewModel) { viewModel.setupRingtones() } - LaunchedEffect(context.alarmManager.hasAlarmPermission) { - context.startAlarmPermission() - } + LaunchedEffect(context.alarmManager.hasAlarmPermission) { context.startAlarmPermission() } AlarmScreen( modifier = Modifier.fillMaxSize(), @@ -127,9 +124,10 @@ fun AlarmScreen( onSaveClicked: OnClick, ) { val context = LocalContext.current - val ringtonePlayer = remember(ringtone) { - RingtoneManager.getRingtone(context, ringtone.value.uriContent.toUri()) - } + val ringtonePlayer = + remember(ringtone) { + RingtoneManager.getRingtone(context, ringtone.value.uriContent.toUri()) + } var ringtoneShowModal by remember { mutableStateOf(false) } var repeatShowModal by remember { mutableStateOf(false) } @@ -177,16 +175,13 @@ fun AlarmScreen( ) { MultiModalSelector( title = stringResource(id = R.string.custom), - currentValues = repeat.value.asCustom()?.customWeekDays?.mapToModalValue() - .orEmpty(), + currentValues = + repeat.value.asCustom()?.customWeekDays?.mapToModalValue().orEmpty(), values = WeekDay.entries.toList().mapToModalValue(), onValuesSelected = { weekDays -> val repeatMode = RepeatMode.Custom(weekDays.map { it.value }) onRepeatChanged( - ModalValue( - context.getString(repeatMode.display), - repeatMode, - ), + ModalValue(context.getString(repeatMode.display), repeatMode) ) showCustomSelector = false repeatShowModal = false @@ -220,22 +215,15 @@ private fun AlarmContent( Section( modifier = modifier, title = stringResource(R.string.alarm_title), - trailingIcon = { - AnimatedButtonIcon(icon = Icons.Back, onClick = onBackPressed) - }, + trailingIcon = { AnimatedButtonIcon(icon = Icons.Back, onClick = onBackPressed) }, headerAnimation = Animation.None, ) { TimerBox( - modifier = Modifier - .fillMaxWidth() - .weight(1F) - .paddingScreen(), + modifier = Modifier.fillMaxWidth().weight(1F).paddingScreen(), onTimeChange = onTimeChanged, ) Selector( - modifier = Modifier - .fillMaxWidth() - .paddingScreen(vertical = 16.dp), + modifier = Modifier.fillMaxWidth().paddingScreen(vertical = 16.dp), title = stringResource(R.string.ringtone), onModalStateChanged = onRingtoneModalStateChanged, showModal = ringtoneShowModal, @@ -243,9 +231,7 @@ private fun AlarmContent( content = ringtoneContent, ) Selector( - modifier = Modifier - .fillMaxWidth() - .paddingScreen(vertical = 16.dp), + modifier = Modifier.fillMaxWidth().paddingScreen(vertical = 16.dp), title = stringResource(R.string.repeat), showModal = repeatShowModal, onModalStateChanged = onRepeatModalStateChanged, @@ -253,10 +239,7 @@ private fun AlarmContent( content = repeatContent, ) Button( - modifier = Modifier - .fillMaxWidth() - .padding(vertical = 16.dp) - .paddingScreen(), + modifier = Modifier.fillMaxWidth().padding(vertical = 16.dp).paddingScreen(), text = stringResource(R.string.save), onClick = onSaveClicked, ) @@ -270,8 +253,7 @@ fun RingtoneEffect(ringtonePlayer: android.media.Ringtone, isModalVisible: Boole LaunchedEffect(lifecycleState) { if ( - lifecycleState == Lifecycle.Event.ON_STOP || - lifecycleState == Lifecycle.Event.ON_PAUSE + lifecycleState == Lifecycle.Event.ON_STOP || lifecycleState == Lifecycle.Event.ON_PAUSE ) { ringtonePlayer.stop() } @@ -279,15 +261,13 @@ fun RingtoneEffect(ringtonePlayer: android.media.Ringtone, isModalVisible: Boole LaunchedEffect(ringtonePlayer) { if (isModalVisible && !ringtonePlayer.isPlaying) { - ringtonePlayer.audioAttributes = AudioAttributes - .Builder() - .setContentType(AudioAttributes.CONTENT_TYPE_SONIFICATION) - .build() + ringtonePlayer.audioAttributes = + AudioAttributes.Builder() + .setContentType(AudioAttributes.CONTENT_TYPE_SONIFICATION) + .build() ringtonePlayer.play() } } - LaunchedEffect(isModalVisible) { - if (!isModalVisible) ringtonePlayer.stop() - } + LaunchedEffect(isModalVisible) { if (!isModalVisible) ringtonePlayer.stop() } } diff --git a/features/alarm/src/main/java/com/ujizin/leafy/alarm/ui/AlarmViewModel.kt b/features/alarm/src/main/java/com/ujizin/leafy/alarm/ui/AlarmViewModel.kt index 8c4b1950..c2093f05 100644 --- a/features/alarm/src/main/java/com/ujizin/leafy/alarm/ui/AlarmViewModel.kt +++ b/features/alarm/src/main/java/com/ujizin/leafy/alarm/ui/AlarmViewModel.kt @@ -16,6 +16,8 @@ import com.ujizin.leafy.domain.usecase.plant.add.AddPlantUseCase import com.ujizin.leafy.domain.usecase.plant.load.LoadDraftPlantUseCase import com.ujizin.leafy.domain.usecase.ringtone.load.LoadRingtonesUseCase import dagger.hilt.android.lifecycle.HiltViewModel +import java.io.File +import javax.inject.Inject import kotlinx.coroutines.ExperimentalCoroutinesApi import kotlinx.coroutines.flow.MutableStateFlow import kotlinx.coroutines.flow.StateFlow @@ -26,11 +28,11 @@ import kotlinx.coroutines.flow.map import kotlinx.coroutines.flow.onCompletion import kotlinx.coroutines.flow.onEach import kotlinx.coroutines.flow.update -import java.io.File -import javax.inject.Inject @HiltViewModel -class AlarmViewModel @Inject constructor( +class AlarmViewModel +@Inject +constructor( private val loadDraftPlant: LoadDraftPlantUseCase, private val addPlant: AddPlantUseCase, private val addAlarm: AddAlarmUseCase, @@ -69,30 +71,32 @@ class AlarmViewModel @Inject constructor( .flatMapConcat { plant -> addPlant(plant.copy(id = 0)).flatMapConcat { id -> addAlarm( - Alarm( - plantId = id, - ringtoneUriContent = ringtoneContent, - minutes = minutes, - hours = hours, - weekDays = weekDays.sorted(), - enabled = true, - ), - ).onEach { alarmId -> - alarmScheduler.scheduleAlarm( - dayOfWeek = weekDays.getNearestDay(hours, minutes).ordinal + 1, - hours = hours, - minutes = minutes, - ringtoneUri = ringtoneContent, - requestCode = alarmId.toInt(), - bundle = bundleOf(AlarmReceiver.ALARM_ID_EXTRA to alarmId), + Alarm( + plantId = id, + ringtoneUriContent = ringtoneContent, + minutes = minutes, + hours = hours, + weekDays = weekDays.sorted(), + enabled = true, + ) ) - } + .onEach { alarmId -> + alarmScheduler.scheduleAlarm( + dayOfWeek = weekDays.getNearestDay(hours, minutes).ordinal + 1, + hours = hours, + minutes = minutes, + ringtoneUri = ringtoneContent, + requestCode = alarmId.toInt(), + bundle = bundleOf(AlarmReceiver.ALARM_ID_EXTRA to alarmId), + ) + } } } .onCompletion { onPlantPublished() } .catch { // Handle error - }.launchIn(viewModelScope) + } + .launchIn(viewModelScope) } } diff --git a/features/alarm/src/main/java/com/ujizin/leafy/alarm/ui/components/AutoSizeText.kt b/features/alarm/src/main/java/com/ujizin/leafy/alarm/ui/components/AutoSizeText.kt index 05ceaf9f..1f0b5d8e 100644 --- a/features/alarm/src/main/java/com/ujizin/leafy/alarm/ui/components/AutoSizeText.kt +++ b/features/alarm/src/main/java/com/ujizin/leafy/alarm/ui/components/AutoSizeText.kt @@ -11,11 +11,7 @@ import androidx.compose.ui.draw.drawWithContent import androidx.compose.ui.text.TextStyle @Composable -fun AutoSizeText( - modifier: Modifier = Modifier, - text: String, - textStyle: TextStyle, -) { +fun AutoSizeText(modifier: Modifier = Modifier, text: String, textStyle: TextStyle) { var scaledTextStyle by remember { mutableStateOf(textStyle) } var readyToDraw by remember { mutableStateOf(false) } @@ -30,8 +26,7 @@ fun AutoSizeText( softWrap = false, onTextLayout = { textLayoutResult -> if (textLayoutResult.didOverflowWidth) { - scaledTextStyle = - scaledTextStyle.copy(fontSize = scaledTextStyle.fontSize * 0.9) + scaledTextStyle = scaledTextStyle.copy(fontSize = scaledTextStyle.fontSize * 0.9) } else { readyToDraw = true } diff --git a/features/alarm/src/main/java/com/ujizin/leafy/alarm/ui/components/modal/ModalValue.kt b/features/alarm/src/main/java/com/ujizin/leafy/alarm/ui/components/modal/ModalValue.kt index 80dc9dcc..10bd1b07 100644 --- a/features/alarm/src/main/java/com/ujizin/leafy/alarm/ui/components/modal/ModalValue.kt +++ b/features/alarm/src/main/java/com/ujizin/leafy/alarm/ui/components/modal/ModalValue.kt @@ -1,6 +1,3 @@ package com.ujizin.leafy.alarm.ui.components.modal -data class ModalValue( - val name: String, - val value: T, -) +data class ModalValue(val name: String, val value: T) diff --git a/features/alarm/src/main/java/com/ujizin/leafy/alarm/ui/components/modal/MultiModalSelector.kt b/features/alarm/src/main/java/com/ujizin/leafy/alarm/ui/components/modal/MultiModalSelector.kt index a00b329d..e9ad1243 100644 --- a/features/alarm/src/main/java/com/ujizin/leafy/alarm/ui/components/modal/MultiModalSelector.kt +++ b/features/alarm/src/main/java/com/ujizin/leafy/alarm/ui/components/modal/MultiModalSelector.kt @@ -30,13 +30,10 @@ internal fun MultiModalSelector( values: List>, onValuesSelected: (List>) -> Unit, ) { - val selectedValues = remember(currentValues) { - mutableStateListOf(*currentValues.toTypedArray()) - } + val selectedValues = + remember(currentValues) { mutableStateListOf(*currentValues.toTypedArray()) } - Column( - modifier = modifier, - ) { + Column(modifier = modifier) { Text( modifier = Modifier.padding(horizontal = 20.dp), text = title.capitalize(), @@ -46,23 +43,17 @@ internal fun MultiModalSelector( LazyColumn { items(values) { item -> ModalItemSelector( - Modifier - .fillMaxWidth() - .padding(horizontal = 20.dp, vertical = 16.dp), + Modifier.fillMaxWidth().padding(horizontal = 20.dp, vertical = 16.dp), text = item.name.capitalize(), selected = selectedValues.contains(item), onItemSelectorClicked = { - with(selectedValues) { - if (contains(item)) remove(item) else add(item) - } + with(selectedValues) { if (contains(item)) remove(item) else add(item) } }, ) } } Button( - modifier = Modifier - .fillMaxWidth() - .paddingScreen(vertical = 16.dp), + modifier = Modifier.fillMaxWidth().paddingScreen(vertical = 16.dp), text = stringResource(R.string.save), enabled = selectedValues.isNotEmpty(), onClick = { onValuesSelected(selectedValues) }, diff --git a/features/alarm/src/main/java/com/ujizin/leafy/alarm/ui/components/timerbox/Timer.kt b/features/alarm/src/main/java/com/ujizin/leafy/alarm/ui/components/timerbox/Timer.kt index 69b68cc3..a83ba922 100644 --- a/features/alarm/src/main/java/com/ujizin/leafy/alarm/ui/components/timerbox/Timer.kt +++ b/features/alarm/src/main/java/com/ujizin/leafy/alarm/ui/components/timerbox/Timer.kt @@ -3,6 +3,7 @@ package com.ujizin.leafy.alarm.ui.components.timerbox import com.ujizin.leafy.core.ui.extensions.toDecimalFormat internal fun List.toDecimalFormat() = map { it.toDecimalFormat() } + internal enum class TimeUnit(val numbers: List) { Hour((0..23).toList().toDecimalFormat()), Minutes((0..59).toList().toDecimalFormat()), diff --git a/features/alarm/src/main/java/com/ujizin/leafy/alarm/ui/components/timerbox/TimerBox.kt b/features/alarm/src/main/java/com/ujizin/leafy/alarm/ui/components/timerbox/TimerBox.kt index 2c278e9d..8d5cd8c5 100644 --- a/features/alarm/src/main/java/com/ujizin/leafy/alarm/ui/components/timerbox/TimerBox.kt +++ b/features/alarm/src/main/java/com/ujizin/leafy/alarm/ui/components/timerbox/TimerBox.kt @@ -36,9 +36,10 @@ import kotlin.math.floor /** * Timer box with hour (00-23) and minute (00-59) + * * @param hour initial hour from timer, valid values (00-23) * @param minute initial - * */ + */ @Composable fun TimerBox( modifier: Modifier = Modifier, @@ -69,10 +70,7 @@ fun TimerBox( ) LaunchedEffect(internalHour, internalMinute) { - onTimeChange( - internalHour.toInt(), - internalMinute.toInt(), - ) + onTimeChange(internalHour.toInt(), internalMinute.toInt()) } } } @@ -85,7 +83,7 @@ fun TimerBox( * @param value the initial value from time unit, if value is not valid then start with 00 * @param horizontalAlignment horizontal alignment from box * @param onTimeChange callback for time unit - * */ + */ @Composable private fun TimerUnitBox( modifier: Modifier = Modifier, @@ -99,11 +97,7 @@ private fun TimerUnitBox( var hapticInitialized by remember { mutableStateOf(false) } val quantityMiddle = remember(quantity) { floor(quantity.toDouble() / 2).toInt() } - LazyColumn( - modifier = modifier, - state = state, - horizontalAlignment = horizontalAlignment, - ) { + LazyColumn(modifier = modifier, state = state, horizontalAlignment = horizontalAlignment) { items(Int.MAX_VALUE) { listIndex -> val index = listIndex % timeUnit.numbers.size val number = timeUnit.numbers[index] @@ -114,36 +108,34 @@ private fun TimerUnitBox( derivedStateOf { state.firstVisibleItemIndex + (quantity - 1) } } - val alpha by remember(listIndex) { - derivedStateOf { - when (listIndex) { - state.firstVisibleItemIndex, endIndex -> 0.25F - middle -> 1F - in state.firstVisibleItemIndex until middle, - in middle until endIndex, - -> 0.5F + val alpha by + remember(listIndex) { + derivedStateOf { + when (listIndex) { + state.firstVisibleItemIndex, + endIndex -> 0.25F + middle -> 1F + in state.firstVisibleItemIndex until middle, + in middle until endIndex -> 0.5F - else -> 0F + else -> 0F + } } } - } val scaleMultiplier = remember(Unit) { 1.4F } val animatedScale by animateFloatAsState(targetValue = alpha * scaleMultiplier) AutoSizeText( - modifier = Modifier - .alpha(alpha) - .scale( - animatedScale.coerceAtLeast(0.5F), - ), + modifier = Modifier.alpha(alpha).scale(animatedScale.coerceAtLeast(0.5F)), text = number, - textStyle = TextStyle( - fontSize = 48.sp, - textAlign = TextAlign.Center, - color = MaterialTheme.colorScheme.onBackground, - fontWeight = FontWeight.Bold, - ), + textStyle = + TextStyle( + fontSize = 48.sp, + textAlign = TextAlign.Center, + color = MaterialTheme.colorScheme.onBackground, + fontWeight = FontWeight.Bold, + ), ) val haptic = LocalHapticFeedback.current @@ -159,9 +151,8 @@ private fun TimerUnitBox( val half = Int.MAX_VALUE / 2 // Set Infinite loop val index = half % timeUnit.numbers.size val zeroIndex = half - index - quantityMiddle - val scrollToIndex = zeroIndex + timeUnit.numbers.indexOf( - value.toDecimalFormat(), - ).coerceAtLeast(0) + val scrollToIndex = + zeroIndex + timeUnit.numbers.indexOf(value.toDecimalFormat()).coerceAtLeast(0) state.scrollToItem(scrollToIndex) } diff --git a/features/alarm/src/main/java/com/ujizin/leafy/alarm/usecase/SchedulePlantAlarmUseCase.kt b/features/alarm/src/main/java/com/ujizin/leafy/alarm/usecase/SchedulePlantAlarmUseCase.kt index d8c0b9ce..5ed106ca 100644 --- a/features/alarm/src/main/java/com/ujizin/leafy/alarm/usecase/SchedulePlantAlarmUseCase.kt +++ b/features/alarm/src/main/java/com/ujizin/leafy/alarm/usecase/SchedulePlantAlarmUseCase.kt @@ -12,9 +12,7 @@ import kotlinx.coroutines.flow.filter import kotlinx.coroutines.flow.flatMapConcat import kotlinx.coroutines.flow.onEach -/** - * Schedule plant alarm use case - * */ +/** Schedule plant alarm use case */ class SchedulePlantAlarmUseCase( private val loadPlant: LoadPlantUseCase, private val loadAlarm: LoadAlarmUseCase, @@ -22,11 +20,12 @@ class SchedulePlantAlarmUseCase( ) { @OptIn(ExperimentalCoroutinesApi::class) - operator fun invoke(alarmId: Long, actualDay: WeekDay = currentDay) = loadAlarm(alarmId) - .mapResult() - .onEach { alarmScheduler.scheduleAlarm(it, actualDay) } - .filter { alarm -> alarm.enabled && alarm.checkDayOfTheWeek() } - .flatMapConcat { alarm -> loadPlant(alarm.plantId).mapResult() } + operator fun invoke(alarmId: Long, actualDay: WeekDay = currentDay) = + loadAlarm(alarmId) + .mapResult() + .onEach { alarmScheduler.scheduleAlarm(it, actualDay) } + .filter { alarm -> alarm.enabled && alarm.checkDayOfTheWeek() } + .flatMapConcat { alarm -> loadPlant(alarm.plantId).mapResult() } private fun Alarm.checkDayOfTheWeek(): Boolean { return weekDays.contains(currentDay) diff --git a/features/alarm/src/test/java/com/ujizin/leafy/alarm/AlarmTestHelper.kt b/features/alarm/src/test/java/com/ujizin/leafy/alarm/AlarmTestHelper.kt index 4d43a288..e01b5c7b 100644 --- a/features/alarm/src/test/java/com/ujizin/leafy/alarm/AlarmTestHelper.kt +++ b/features/alarm/src/test/java/com/ujizin/leafy/alarm/AlarmTestHelper.kt @@ -13,8 +13,7 @@ object AlarmTestHelper { enabled: Boolean = true, hours: Int = Random.nextInt(23), minutes: Int = Random.nextInt(59), - weekDays: List = (0..6).shuffled().take(Random.nextInt(1, 6)).map { - WeekDay.entries[it] - }, + weekDays: List = + (0..6).shuffled().take(Random.nextInt(1, 6)).map { WeekDay.entries[it] }, ) = Alarm(id, plantId, ringtoneContent, hours, enabled, minutes, weekDays) } diff --git a/features/alarm/src/test/java/com/ujizin/leafy/alarm/SchedulePlantAlarmUseCaseTest.kt b/features/alarm/src/test/java/com/ujizin/leafy/alarm/SchedulePlantAlarmUseCaseTest.kt index f7723b35..99a76ad7 100644 --- a/features/alarm/src/test/java/com/ujizin/leafy/alarm/SchedulePlantAlarmUseCaseTest.kt +++ b/features/alarm/src/test/java/com/ujizin/leafy/alarm/SchedulePlantAlarmUseCaseTest.kt @@ -11,6 +11,8 @@ import com.ujizin.leafy.domain.model.WeekDay import io.mockk.every import io.mockk.mockkConstructor import io.mockk.mockkStatic +import java.util.Calendar +import java.util.Calendar.DAY_OF_WEEK import junit.framework.TestCase.assertEquals import junit.framework.TestCase.assertNotNull import kotlinx.coroutines.flow.flowOn @@ -21,14 +23,11 @@ import org.junit.Rule import org.junit.Test import org.junit.runner.RunWith import org.junit.runners.JUnit4 -import java.util.Calendar -import java.util.Calendar.DAY_OF_WEEK @RunWith(JUnit4::class) class SchedulePlantAlarmUseCaseTest { - @get:Rule - val mainDispatcherRule = TestDispatcherRule() + @get:Rule val mainDispatcherRule = TestDispatcherRule() private val alarmScheduler = FakeAlarmScheduler() @@ -36,11 +35,12 @@ class SchedulePlantAlarmUseCaseTest { private val loadAlarm = FakeLoadAlarmUseCase(until = COUNTER) - val schedulePlantAlarm = SchedulePlantAlarmUseCase( - loadPlant = loadPlant, - loadAlarm = loadAlarm, - alarmScheduler = alarmScheduler, - ) + val schedulePlantAlarm = + SchedulePlantAlarmUseCase( + loadPlant = loadPlant, + loadAlarm = loadAlarm, + alarmScheduler = alarmScheduler, + ) @Test fun `test alarm is scheduled will ring in exact time whether enabled`() { @@ -65,9 +65,11 @@ class SchedulePlantAlarmUseCaseTest { .collect { isFlowCollected = true - val alarmScheduled = alarmScheduler.alarms.find { scheduled -> - scheduled.hours == alarm.hours && scheduled.minutes == alarm.minutes - } + val alarmScheduled = + alarmScheduler.alarms.find { scheduled -> + scheduled.hours == alarm.hours && + scheduled.minutes == alarm.minutes + } assertNotNull(alarmScheduled) assertEquals(alarm.plantId, it.id) diff --git a/features/alarm/src/test/java/com/ujizin/leafy/alarm/WeekDayExtensionsTest.kt b/features/alarm/src/test/java/com/ujizin/leafy/alarm/WeekDayExtensionsTest.kt index b36c7cca..1da2dfb7 100644 --- a/features/alarm/src/test/java/com/ujizin/leafy/alarm/WeekDayExtensionsTest.kt +++ b/features/alarm/src/test/java/com/ujizin/leafy/alarm/WeekDayExtensionsTest.kt @@ -3,9 +3,9 @@ package com.ujizin.leafy.alarm import com.ujizin.leafy.core.ui.extensions.plus import com.ujizin.leafy.core.ui.extensions.reorderByCurrentDay import com.ujizin.leafy.domain.model.WeekDay +import kotlin.random.Random import org.junit.Assert import org.junit.Test -import kotlin.random.Random class WeekDayExtensionsTest { diff --git a/features/alarm/src/test/java/com/ujizin/leafy/alarm/fakes/FakeAlarmScheduler.kt b/features/alarm/src/test/java/com/ujizin/leafy/alarm/fakes/FakeAlarmScheduler.kt index c40f4dd4..b557a639 100644 --- a/features/alarm/src/test/java/com/ujizin/leafy/alarm/fakes/FakeAlarmScheduler.kt +++ b/features/alarm/src/test/java/com/ujizin/leafy/alarm/fakes/FakeAlarmScheduler.kt @@ -16,7 +16,8 @@ class FakeAlarmScheduler : AlarmScheduler { ) private val _alarms = mutableListOf() - val alarms get() = _alarms.toList() + val alarms + get() = _alarms.toList() override fun scheduleAlarm( type: Int, @@ -27,15 +28,16 @@ class FakeAlarmScheduler : AlarmScheduler { requestCode: Int, bundle: Bundle, ) { - _alarms += FakeAlarm( - id = requestCode, - dayOfWeek = dayOfWeek, - type = type, - hours = hours, - minutes = minutes, - ringtoneUri = ringtoneUri, - bundle = bundle, - ) + _alarms += + FakeAlarm( + id = requestCode, + dayOfWeek = dayOfWeek, + type = type, + hours = hours, + minutes = minutes, + ringtoneUri = ringtoneUri, + bundle = bundle, + ) } override fun cancelAlarm(requestCode: Int) { diff --git a/features/alarm/src/test/java/com/ujizin/leafy/alarm/fakes/FakeLoadAlarmUseCase.kt b/features/alarm/src/test/java/com/ujizin/leafy/alarm/fakes/FakeLoadAlarmUseCase.kt index 2e2e18c0..d0c6fb7c 100644 --- a/features/alarm/src/test/java/com/ujizin/leafy/alarm/fakes/FakeLoadAlarmUseCase.kt +++ b/features/alarm/src/test/java/com/ujizin/leafy/alarm/fakes/FakeLoadAlarmUseCase.kt @@ -8,15 +8,14 @@ import kotlinx.coroutines.flow.flow class FakeLoadAlarmUseCase( private val until: Int = 10, - val alarms: MutableList = (0..until).map { - createAlarm(id = it + 1L, plantId = it + 1L) - }.toMutableList(), + val alarms: MutableList = + (0..until).map { createAlarm(id = it + 1L, plantId = it + 1L) }.toMutableList(), ) : LoadAlarmUseCase { override fun invoke(id: Long) = flow { - val result = alarms.find { it.id == id }?.let { - Result.Success(it) - } ?: Result.Error(Exception("Alarm with id: $id not found")) + val result = + alarms.find { it.id == id }?.let { Result.Success(it) } + ?: Result.Error(Exception("Alarm with id: $id not found")) emit(result) } diff --git a/features/alarm/src/test/java/com/ujizin/leafy/alarm/fakes/FakeLoadPlant.kt b/features/alarm/src/test/java/com/ujizin/leafy/alarm/fakes/FakeLoadPlant.kt index c4088028..60d0ed5c 100644 --- a/features/alarm/src/test/java/com/ujizin/leafy/alarm/fakes/FakeLoadPlant.kt +++ b/features/alarm/src/test/java/com/ujizin/leafy/alarm/fakes/FakeLoadPlant.kt @@ -10,13 +10,14 @@ class FakeLoadPlant( private val plants: List = (0..until).map { createPlant(id = it + 1L) }, ) : LoadPlantUseCase { - override fun invoke(id: Long) = flow> { - val result = plants.find { it.id == id }?.let { - Result.Success(it) - } ?: Result.Error(Exception("Plant with id: $id not found")) + override fun invoke(id: Long) = + flow> { + val result = + plants.find { it.id == id }?.let { Result.Success(it) } + ?: Result.Error(Exception("Plant with id: $id not found")) - emit(result) - } + emit(result) + } companion object { private fun createPlant( diff --git a/features/camera/build.gradle.kts b/features/camera/build.gradle.kts index 03399187..96584fdd 100644 --- a/features/camera/build.gradle.kts +++ b/features/camera/build.gradle.kts @@ -1,20 +1,8 @@ -plugins { - alias(libs.plugins.android.library) - alias(libs.plugins.kotlin.android) -} - -apply(from = "$rootDir/config-compose.gradle") -apply(from = "$rootDir/config-android.gradle") +plugins { id("com.ujizin.android-feature") } -android { - namespace = "com.ujizin.leafy.features.camera" -} +android { namespace = "com.ujizin.leafy.features.camera" } dependencies { - implementation(projects.core.navigation) - implementation(projects.core.ui) - implementation(projects.domain) - implementation(libs.accompanist.permissions) implementation(libs.coil) implementation(libs.camposer) diff --git a/features/camera/src/main/java/com/ujizin/leafy/camera/CameraNavigation.kt b/features/camera/src/main/java/com/ujizin/leafy/camera/CameraNavigation.kt index 86a87fd4..60dcfd6c 100644 --- a/features/camera/src/main/java/com/ujizin/leafy/camera/CameraNavigation.kt +++ b/features/camera/src/main/java/com/ujizin/leafy/camera/CameraNavigation.kt @@ -11,10 +11,7 @@ import com.ujizin.leafy.camera.ui.CameraRoute import com.ujizin.leafy.core.navigation.Destination import com.ujizin.leafy.core.ui.extensions.OnClick -fun NavGraphBuilder.cameraGraph( - onBackPressed: OnClick, - onSaveClicked: () -> Unit, -) { +fun NavGraphBuilder.cameraGraph(onBackPressed: OnClick, onSaveClicked: () -> Unit) { composable( enterTransition = { slideIntoContainer( @@ -31,9 +28,6 @@ fun NavGraphBuilder.cameraGraph( ) }, ) { - CameraRoute( - onCloseClicked = onBackPressed, - onImageSaved = onSaveClicked, - ) + CameraRoute(onCloseClicked = onBackPressed, onImageSaved = onSaveClicked) } } diff --git a/features/camera/src/main/java/com/ujizin/leafy/camera/ui/CameraDenied.kt b/features/camera/src/main/java/com/ujizin/leafy/camera/ui/CameraDenied.kt index dec8fac0..4c0979e4 100644 --- a/features/camera/src/main/java/com/ujizin/leafy/camera/ui/CameraDenied.kt +++ b/features/camera/src/main/java/com/ujizin/leafy/camera/ui/CameraDenied.kt @@ -22,14 +22,15 @@ internal fun CameraDenied( onBackPressed: () -> Unit, onCameraRequest: OnClick, ) { - val descriptionRes by remember(shouldShowRationale) { - mutableIntStateOf( - when { - shouldShowRationale -> R.string.camera_permission_description - else -> R.string.camera_permission_denied_description - }, - ) - } + val descriptionRes by + remember(shouldShowRationale) { + mutableIntStateOf( + when { + shouldShowRationale -> R.string.camera_permission_description + else -> R.string.camera_permission_denied_description + } + ) + } AnimatedButtonIcon( modifier = Modifier.paddingScreen(vertical = 24.dp), icon = Icons.Back, diff --git a/features/camera/src/main/java/com/ujizin/leafy/camera/ui/CameraPreviewSection.kt b/features/camera/src/main/java/com/ujizin/leafy/camera/ui/CameraPreviewSection.kt index 39cd2bb0..547d484f 100644 --- a/features/camera/src/main/java/com/ujizin/leafy/camera/ui/CameraPreviewSection.kt +++ b/features/camera/src/main/java/com/ujizin/leafy/camera/ui/CameraPreviewSection.kt @@ -26,21 +26,14 @@ internal fun CameraPreviewSection( ) { BackHandler(onBack = onBackPressed) Box(Modifier.fillMaxSize()) { - AsyncImage( - modifier = Modifier.fillMaxSize(), - model = bitmap, - contentDescription = null, - ) + AsyncImage(modifier = Modifier.fillMaxSize(), model = bitmap, contentDescription = null) AnimatedButtonIcon( modifier = Modifier.padding(16.dp), icon = Icons.Back, onClick = onBackPressed, ) Button( - modifier = Modifier - .padding(20.dp) - .fillMaxWidth() - .align(Alignment.BottomCenter), + modifier = Modifier.padding(20.dp).fillMaxWidth().align(Alignment.BottomCenter), text = stringResource(id = R.string.save), onClick = { onSaveClicked(bitmap) }, ) diff --git a/features/camera/src/main/java/com/ujizin/leafy/camera/ui/CameraRoute.kt b/features/camera/src/main/java/com/ujizin/leafy/camera/ui/CameraRoute.kt index 32d4df6d..a79c9b04 100644 --- a/features/camera/src/main/java/com/ujizin/leafy/camera/ui/CameraRoute.kt +++ b/features/camera/src/main/java/com/ujizin/leafy/camera/ui/CameraRoute.kt @@ -34,52 +34,51 @@ internal fun CameraRoute( PermissionStatus.Granted -> { val uiState by viewModel.uiState.collectAsStateWithLifecycle() val cameraState = rememberCameraState() - val launcher = rememberLauncherForActivityResult(PickVisualMedia()) launcher@{ uri -> - if (uri == null) return@launcher - viewModel.preparePreview( - contentResolver = context.contentResolver, - uri = uri, - ) - } + val launcher = + rememberLauncherForActivityResult(PickVisualMedia()) launcher@{ uri -> + if (uri == null) return@launcher + viewModel.preparePreview(contentResolver = context.contentResolver, uri = uri) + } when (val state = uiState) { - is CameraUiState.Preview -> CameraPreviewSection( - bitmap = state.bitmap, - onBackPressed = viewModel::onBackCamera, - onSaveClicked = { - viewModel.saveImage( - context = context, - bitmap = state.bitmap, - onImageSaved = onImageSaved, - ) - }, - ) + is CameraUiState.Preview -> + CameraPreviewSection( + bitmap = state.bitmap, + onBackPressed = viewModel::onBackCamera, + onSaveClicked = { + viewModel.saveImage( + context = context, + bitmap = state.bitmap, + onImageSaved = onImageSaved, + ) + }, + ) - else -> Camera( - uiState = state, - cameraState = cameraState, - onCloseClicked = onCloseClicked, - onTakePicture = { viewModel.takePicture(cameraState) }, - onGalleryClick = { - launcher.launch(PickVisualMediaRequest(PickVisualMedia.ImageOnly)) - }, - ) + else -> + Camera( + uiState = state, + cameraState = cameraState, + onCloseClicked = onCloseClicked, + onTakePicture = { viewModel.takePicture(cameraState) }, + onGalleryClick = { + launcher.launch(PickVisualMediaRequest(PickVisualMedia.ImageOnly)) + }, + ) } } - is PermissionStatus.Denied -> CameraDenied( - shouldShowRationale = status.shouldShowRationale, - onBackPressed = onCloseClicked, - ) { - if (status.shouldShowRationale) { - cameraPermissionState.launchPermissionRequest() - } else { - context.startSettingsPermission() + is PermissionStatus.Denied -> + CameraDenied( + shouldShowRationale = status.shouldShowRationale, + onBackPressed = onCloseClicked, + ) { + if (status.shouldShowRationale) { + cameraPermissionState.launchPermissionRequest() + } else { + context.startSettingsPermission() + } } - } } - LaunchedEffect(Unit) { - cameraPermissionState.launchPermissionRequest() - } + LaunchedEffect(Unit) { cameraPermissionState.launchPermissionRequest() } } diff --git a/features/camera/src/main/java/com/ujizin/leafy/camera/ui/camera/Camera.kt b/features/camera/src/main/java/com/ujizin/leafy/camera/ui/camera/Camera.kt index 8e483cdf..f8d41133 100644 --- a/features/camera/src/main/java/com/ujizin/leafy/camera/ui/camera/Camera.kt +++ b/features/camera/src/main/java/com/ujizin/leafy/camera/ui/camera/Camera.kt @@ -55,9 +55,7 @@ internal fun Camera( onCloseClicked = onCloseClicked, ) CameraFooter( - modifier = Modifier - .fillMaxWidth() - .padding(horizontal = 48.dp, vertical = 32.dp), + modifier = Modifier.fillMaxWidth().padding(horizontal = 48.dp, vertical = 32.dp), onTakePicture = onTakePicture, onGalleryClick = onGalleryClick, onSwitchClick = { camSelector = camSelector.inverse }, @@ -69,7 +67,5 @@ internal fun Camera( @Composable private fun ErrorPopUp(message: String) { val context = LocalContext.current - LaunchedEffect(message) { - Toast.makeText(context, message, Toast.LENGTH_SHORT).show() - } + LaunchedEffect(message) { Toast.makeText(context, message, Toast.LENGTH_SHORT).show() } } diff --git a/features/camera/src/main/java/com/ujizin/leafy/camera/ui/camera/CameraFooter.kt b/features/camera/src/main/java/com/ujizin/leafy/camera/ui/camera/CameraFooter.kt index bc6e4f97..311d78ba 100644 --- a/features/camera/src/main/java/com/ujizin/leafy/camera/ui/camera/CameraFooter.kt +++ b/features/camera/src/main/java/com/ujizin/leafy/camera/ui/camera/CameraFooter.kt @@ -41,44 +41,26 @@ fun CameraFooter( onGalleryClick: OnClick, onSwitchClick: OnClick, ) { - Box( - modifier = Modifier - .noClickable() - .then(modifier), - ) { - ButtonGallery( - modifier = Modifier.align(Alignment.CenterStart), - onClick = onGalleryClick, - ) - ButtonPicture( - modifier = Modifier.align(Alignment.Center), - onClick = onTakePicture, - ) - ButtonSwitchCamera( - modifier = Modifier.align(Alignment.CenterEnd), - onClick = onSwitchClick, - ) + Box(modifier = Modifier.noClickable().then(modifier)) { + ButtonGallery(modifier = Modifier.align(Alignment.CenterStart), onClick = onGalleryClick) + ButtonPicture(modifier = Modifier.align(Alignment.Center), onClick = onTakePicture) + ButtonSwitchCamera(modifier = Modifier.align(Alignment.CenterEnd), onClick = onSwitchClick) } } @Composable -fun ButtonSwitchCamera( - modifier: Modifier = Modifier, - onClick: OnClick, -) { +fun ButtonSwitchCamera(modifier: Modifier = Modifier, onClick: OnClick) { var rotate by remember { mutableStateOf(false) } - val rotateAnimation by animateFloatAsState( - targetValue = if (rotate) 0F else 180F, - label = "camera-button-switch", - ) + val rotateAnimation by + animateFloatAsState(targetValue = if (rotate) 0F else 180F, label = "camera-button-switch") ButtonPulse( - modifier = Modifier - .background( - MaterialTheme.colorScheme.secondaryContainer.copy(alpha = 0.5F), - CircleShape, - ) - .padding(12.dp) - .then(modifier), + modifier = + Modifier.background( + MaterialTheme.colorScheme.secondaryContainer.copy(alpha = 0.5F), + CircleShape, + ) + .padding(12.dp) + .then(modifier), shape = CircleShape, onClick = { rotate = !rotate @@ -86,10 +68,7 @@ fun ButtonSwitchCamera( }, ) { AnimatedIcon( - modifier = Modifier - .size(24.dp) - .align(Alignment.Center) - .rotate(rotateAnimation), + modifier = Modifier.size(24.dp).align(Alignment.Center).rotate(rotateAnimation), icon = Icons.Refresh, tint = Color.White, ) @@ -97,25 +76,20 @@ fun ButtonSwitchCamera( } @Composable -fun ButtonGallery( - modifier: Modifier = Modifier, - onClick: OnClick, -) { +fun ButtonGallery(modifier: Modifier = Modifier, onClick: OnClick) { ButtonPulse( - modifier = Modifier - .background( - MaterialTheme.colorScheme.secondaryContainer.copy(alpha = 0.5F), - CircleShape, - ) - .padding(12.dp) - .then(modifier), + modifier = + Modifier.background( + MaterialTheme.colorScheme.secondaryContainer.copy(alpha = 0.5F), + CircleShape, + ) + .padding(12.dp) + .then(modifier), shape = CircleShape, onClick = onClick, ) { AnimatedIcon( - modifier = Modifier - .size(24.dp) - .align(Alignment.Center), + modifier = Modifier.size(24.dp).align(Alignment.Center), icon = Icons.Gallery, tint = Color.White, ) @@ -123,13 +97,9 @@ fun ButtonGallery( } @Composable -private fun ButtonPicture( - modifier: Modifier = Modifier, - onClick: OnClick, -) { +private fun ButtonPicture(modifier: Modifier = Modifier, onClick: OnClick) { ButtonPulse( - Modifier - .size(72.dp) + Modifier.size(72.dp) .background(MaterialTheme.colorScheme.primary, CircleShape) .border(BorderStroke(8.dp, Color.White), CircleShape) .then(modifier), @@ -148,23 +118,24 @@ fun ButtonPulse( ) { val interactionSource = remember { MutableInteractionSource() } val buttonPressed by interactionSource.collectIsPressedAsState() - val scaleAnimated by animateFloatAsState( - targetValue = if (buttonPressed) 1.10F else 1F, - label = "button-pulse-scale", - ) + val scaleAnimated by + animateFloatAsState( + targetValue = if (buttonPressed) 1.10F else 1F, + label = "button-pulse-scale", + ) LaunchedEffect(buttonPressed) { onPressChange(buttonPressed) } Box( - modifier = Modifier - .clip(shape) - .clickable( - interactionSource = interactionSource, - indication = ripple(bounded = true), - onClick = onClick, - ) - .scale(scaleAnimated) - .then(modifier), + modifier = + Modifier.clip(shape) + .clickable( + interactionSource = interactionSource, + indication = ripple(bounded = true), + onClick = onClick, + ) + .scale(scaleAnimated) + .then(modifier), content = content, ) } diff --git a/features/camera/src/main/java/com/ujizin/leafy/camera/ui/camera/CameraHeader.kt b/features/camera/src/main/java/com/ujizin/leafy/camera/ui/camera/CameraHeader.kt index 0b50631d..aaa71cc3 100644 --- a/features/camera/src/main/java/com/ujizin/leafy/camera/ui/camera/CameraHeader.kt +++ b/features/camera/src/main/java/com/ujizin/leafy/camera/ui/camera/CameraHeader.kt @@ -19,16 +19,10 @@ internal fun CameraHeader( onCloseClicked: OnClick, ) { Row( - modifier = Modifier - .fillMaxWidth() - .padding(horizontal = 16.dp, vertical = 16.dp), + modifier = Modifier.fillMaxWidth().padding(horizontal = 16.dp, vertical = 16.dp), horizontalArrangement = Arrangement.SpaceBetween, ) { - AnimatedButtonIcon( - size = 24.dp, - icon = Icons.Back, - onClick = onCloseClicked, - ) + AnimatedButtonIcon(size = 24.dp, icon = Icons.Back, onClick = onCloseClicked) Box() {} Box() {} } diff --git a/features/camera/src/main/java/com/ujizin/leafy/camera/viewmodel/CameraViewModel.kt b/features/camera/src/main/java/com/ujizin/leafy/camera/viewmodel/CameraViewModel.kt index 62493e8e..d7826efb 100644 --- a/features/camera/src/main/java/com/ujizin/leafy/camera/viewmodel/CameraViewModel.kt +++ b/features/camera/src/main/java/com/ujizin/leafy/camera/viewmodel/CameraViewModel.kt @@ -15,22 +15,25 @@ import com.ujizin.leafy.core.ui.extensions.launchCatching import com.ujizin.leafy.domain.usecase.file.save.SaveFileUseCase import com.ujizin.leafy.domain.usecase.plant.add.AddDraftPlantUseCase import dagger.hilt.android.lifecycle.HiltViewModel +import java.io.ByteArrayOutputStream +import javax.inject.Inject import kotlinx.coroutines.flow.MutableStateFlow import kotlinx.coroutines.flow.StateFlow import kotlinx.coroutines.flow.launchIn import kotlinx.coroutines.flow.onCompletion import kotlinx.coroutines.flow.update -import java.io.ByteArrayOutputStream -import javax.inject.Inject @HiltViewModel -class CameraViewModel @Inject constructor( +class CameraViewModel +@Inject +constructor( private val saveFile: SaveFileUseCase, private val addDraftPlant: AddDraftPlantUseCase, ) : ViewModel() { private val _uiState = MutableStateFlow(CameraUiState.Initial) - val uiState: StateFlow get() = _uiState + val uiState: StateFlow + get() = _uiState fun takePicture(cameraState: CameraState) { viewModelScope.launchCatching({ _, exception -> @@ -51,22 +54,13 @@ class CameraViewModel @Inject constructor( _uiState.update { CameraUiState.Initial } } - fun saveImage( - context: Context, - bitmap: Bitmap, - onImageSaved: () -> Unit, - ) { - addDraftPlant( - file = saveFile(context.cacheDir, bitmap, "jpg"), - ).onCompletion { - onImageSaved() - }.launchIn(viewModelScope) + fun saveImage(context: Context, bitmap: Bitmap, onImageSaved: () -> Unit) { + addDraftPlant(file = saveFile(context.cacheDir, bitmap, "jpg")) + .onCompletion { onImageSaved() } + .launchIn(viewModelScope) } - fun preparePreview( - contentResolver: ContentResolver, - uri: Uri, - ) { + fun preparePreview(contentResolver: ContentResolver, uri: Uri) { val inputStream = contentResolver.openInputStream(uri) val bitmap = BitmapFactory.decodeStream(inputStream) @@ -78,6 +72,8 @@ class CameraViewModel @Inject constructor( sealed interface CameraUiState { data object Initial : CameraUiState + data class Preview(val bitmap: Bitmap) : CameraUiState + data class Error(val message: String) : CameraUiState } diff --git a/features/home/build.gradle.kts b/features/home/build.gradle.kts index 818e48a9..49c06b1d 100644 --- a/features/home/build.gradle.kts +++ b/features/home/build.gradle.kts @@ -1,18 +1,3 @@ -plugins { - alias(libs.plugins.android.library) - alias(libs.plugins.kotlin.android) -} +plugins { id("com.ujizin.android-feature") } -apply(from = "$rootDir/config-compose.gradle") -apply(from = "$rootDir/config-android.gradle") - -android { - namespace = "com.ujizin.leafy.features.home" -} - -dependencies { - implementation(projects.core.navigation) - implementation(projects.core.ui) - implementation(projects.core.themes) - implementation(projects.domain) -} +android { namespace = "com.ujizin.leafy.features.home" } diff --git a/features/home/src/main/java/com/ujizin/leafy/home/HomeViewModel.kt b/features/home/src/main/java/com/ujizin/leafy/home/HomeViewModel.kt index b2a40faa..3f797d31 100644 --- a/features/home/src/main/java/com/ujizin/leafy/home/HomeViewModel.kt +++ b/features/home/src/main/java/com/ujizin/leafy/home/HomeViewModel.kt @@ -7,21 +7,21 @@ import com.ujizin.leafy.domain.model.Plant import com.ujizin.leafy.domain.result.mapResult import com.ujizin.leafy.domain.usecase.plant.load.LoadAllPlantUseCase import dagger.hilt.android.lifecycle.HiltViewModel +import javax.inject.Inject import kotlinx.coroutines.flow.MutableStateFlow import kotlinx.coroutines.flow.asStateFlow import kotlinx.coroutines.flow.catch import kotlinx.coroutines.flow.launchIn import kotlinx.coroutines.flow.onEach import kotlinx.coroutines.flow.update -import javax.inject.Inject @HiltViewModel -class HomeViewModel @Inject constructor( - private val loadAllPlant: LoadAllPlantUseCase, -) : ViewModel() { +class HomeViewModel @Inject constructor(private val loadAllPlant: LoadAllPlantUseCase) : + ViewModel() { private val _uiState = MutableStateFlow(HomeUIState.Loading) val uiState = _uiState.asStateFlow() + fun loadHome() { loadAllPlant() .mapResult() @@ -32,12 +32,9 @@ class HomeViewModel @Inject constructor( } sealed interface HomeUIState { - @Immutable - data class Success(val plants: List) : HomeUIState + @Immutable data class Success(val plants: List) : HomeUIState - @Immutable - data class Error(val throwable: Throwable?) : HomeUIState + @Immutable data class Error(val throwable: Throwable?) : HomeUIState - @Immutable - data object Loading : HomeUIState + @Immutable data object Loading : HomeUIState } diff --git a/features/home/src/main/java/com/ujizin/leafy/home/ui/Home.kt b/features/home/src/main/java/com/ujizin/leafy/home/ui/Home.kt index b702b5e0..119057b8 100644 --- a/features/home/src/main/java/com/ujizin/leafy/home/ui/Home.kt +++ b/features/home/src/main/java/com/ujizin/leafy/home/ui/Home.kt @@ -50,20 +50,18 @@ private fun HomeContent( modifier: Modifier = Modifier, onPlantClick: (Long) -> Unit, ) { - Box( - modifier = modifier, - contentAlignment = Alignment.TopCenter, - ) { + Box(modifier = modifier, contentAlignment = Alignment.TopCenter) { when (val result: HomeUIState = state) { HomeUIState.Loading -> {} - is HomeUIState.Success -> HomeSection( - nickname = nickname, - plants = result.plants, - onEmptyPlantClick = onTakePictureClick, - onSearchClick = onSearchClick, - onDrawerClick = onDrawerClick, - onPlantClick = onPlantClick, - ) + is HomeUIState.Success -> + HomeSection( + nickname = nickname, + plants = result.plants, + onEmptyPlantClick = onTakePictureClick, + onSearchClick = onSearchClick, + onDrawerClick = onDrawerClick, + onPlantClick = onPlantClick, + ) is HomeUIState.Error -> {} } diff --git a/features/home/src/main/java/com/ujizin/leafy/home/ui/HomeSection.kt b/features/home/src/main/java/com/ujizin/leafy/home/ui/HomeSection.kt index 5d883cb1..dfdfe3bd 100644 --- a/features/home/src/main/java/com/ujizin/leafy/home/ui/HomeSection.kt +++ b/features/home/src/main/java/com/ujizin/leafy/home/ui/HomeSection.kt @@ -38,15 +38,11 @@ internal fun HomeSection( onPlantClick: (Long) -> Unit, ) { val context = LocalContext.current - NavLazyColumn( - verticalArrangement = Arrangement.spacedBy(16.dp), - ) { + NavLazyColumn(verticalArrangement = Arrangement.spacedBy(16.dp)) { item { Section( - title = stringResource( - id = R.string.hello_user, - nickname.capitalize(), - ).capitalize(), + title = + stringResource(id = R.string.hello_user, nickname.capitalize()).capitalize(), subTitle = stringResource(id = R.string.welcome_back).capitalize(), leadingIcon = { AnimatedButtonIcon( @@ -65,31 +61,28 @@ internal fun HomeSection( ) } when { - plants.isEmpty() -> item { - EmptySection( - modifier = Modifier.padding(vertical = 32.dp, horizontal = 20.dp), - onClick = onEmptyPlantClick, - ) - } + plants.isEmpty() -> + item { + EmptySection( + modifier = Modifier.padding(vertical = 32.dp, horizontal = 20.dp), + onClick = onEmptyPlantClick, + ) + } - else -> items(plants, key = { it.id }) { - HomePlantCard( - plant = it, - onPlantClick = onPlantClick, - onSharedClick = { plant -> - plant.share(context) - }, - ) - } + else -> + items(plants, key = { it.id }) { + HomePlantCard( + plant = it, + onPlantClick = onPlantClick, + onSharedClick = { plant -> plant.share(context) }, + ) + } } } } @Composable -fun NavLazyColumn( - verticalArrangement: Arrangement.Vertical, - content: LazyListScope.() -> Unit, -) { +fun NavLazyColumn(verticalArrangement: Arrangement.Vertical, content: LazyListScope.() -> Unit) { LazyColumn( verticalArrangement = verticalArrangement, horizontalAlignment = Alignment.CenterHorizontally, @@ -107,11 +100,11 @@ private fun LazyItemScope.HomePlantCard( onSharedClick: (Plant) -> Unit, ) { CardPlant( - modifier = Modifier - .animateItemPlacement() - .padding(horizontal = 20.dp) - .fillMaxWidth() - .aspectRatio(1F), + modifier = + Modifier.animateItemPlacement() + .padding(horizontal = 20.dp) + .fillMaxWidth() + .aspectRatio(1F), plant = plant, onClick = { onPlantClick(plant.id) }, onSharedClick = { onSharedClick(plant) }, diff --git a/features/plant/build.gradle.kts b/features/plant/build.gradle.kts index 2fb59a0d..d2eb9797 100644 --- a/features/plant/build.gradle.kts +++ b/features/plant/build.gradle.kts @@ -1,18 +1,3 @@ -plugins { - alias(libs.plugins.android.library) - alias(libs.plugins.kotlin.android) -} +plugins { id("com.ujizin.android-feature") } -apply(from = "$rootDir/config-compose.gradle") -apply(from = "$rootDir/config-android.gradle") - -android { - namespace = "com.ujizin.leafy.features.plant" -} - -dependencies { - implementation(projects.core.navigation) - implementation(projects.core.ui) - implementation(projects.core.themes) - implementation(projects.domain) -} +android { namespace = "com.ujizin.leafy.features.plant" } diff --git a/features/plant/src/main/java/com/ujizin/leafy/features/plant/PlantGraph.kt b/features/plant/src/main/java/com/ujizin/leafy/features/plant/PlantGraph.kt index 57835f87..f5f77ae7 100644 --- a/features/plant/src/main/java/com/ujizin/leafy/features/plant/PlantGraph.kt +++ b/features/plant/src/main/java/com/ujizin/leafy/features/plant/PlantGraph.kt @@ -21,20 +21,11 @@ fun NavGraphBuilder.plantGraph( composable( enterTransition = enterTransition, exitTransition = exitTransition, - deepLinks = listOf( - navDeepLink(basePath = PlantDetails.DEEPLINK_URL), - ), + deepLinks = listOf(navDeepLink(basePath = PlantDetails.DEEPLINK_URL)), ) { - PlantDetailsRoute( - onBackPressed = onBackPressed, - ) + PlantDetailsRoute(onBackPressed = onBackPressed) } - composable( - enterTransition = enterTransition, - exitTransition = exitTransition, - ) { - PlantEditRoute( - onBackPressed = onBackPressed, - ) + composable(enterTransition = enterTransition, exitTransition = exitTransition) { + PlantEditRoute(onBackPressed = onBackPressed) } } diff --git a/features/plant/src/main/java/com/ujizin/leafy/features/plant/detail/PlantDetailsViewModel.kt b/features/plant/src/main/java/com/ujizin/leafy/features/plant/detail/PlantDetailsViewModel.kt index 01b47384..6a5ca97d 100644 --- a/features/plant/src/main/java/com/ujizin/leafy/features/plant/detail/PlantDetailsViewModel.kt +++ b/features/plant/src/main/java/com/ujizin/leafy/features/plant/detail/PlantDetailsViewModel.kt @@ -14,6 +14,7 @@ import com.ujizin.leafy.domain.usecase.alarm.update.UpdateAlarmUseCase import com.ujizin.leafy.domain.usecase.plant.delete.DeletePlantUseCase import com.ujizin.leafy.domain.usecase.plant.load.LoadPlantUseCase import dagger.hilt.android.lifecycle.HiltViewModel +import javax.inject.Inject import kotlinx.coroutines.ExperimentalCoroutinesApi import kotlinx.coroutines.flow.SharingStarted import kotlinx.coroutines.flow.flatMapConcat @@ -21,10 +22,11 @@ import kotlinx.coroutines.flow.launchIn import kotlinx.coroutines.flow.map import kotlinx.coroutines.flow.onCompletion import kotlinx.coroutines.flow.stateIn -import javax.inject.Inject @HiltViewModel -class DetailPlantViewModel @Inject constructor( +class DetailPlantViewModel +@Inject +constructor( savedStateHandle: SavedStateHandle, loadPlant: LoadPlantUseCase, loadAlarms: LoadAlarmsUseCase, @@ -36,19 +38,19 @@ class DetailPlantViewModel @Inject constructor( private val arguments = savedStateHandle.toRoute() @OptIn(ExperimentalCoroutinesApi::class) - val uiState = loadPlant(arguments.plantId) - .mapResult() - .flatMapConcat { plant -> - loadAlarms(plant.id) - .mapResult() - .map { alarms -> + val uiState = + loadPlant(arguments.plantId) + .mapResult() + .flatMapConcat { plant -> + loadAlarms(plant.id).mapResult().map { alarms -> DetailPlantUiState.Loaded(plant, alarms) } - }.stateIn( - scope = viewModelScope, - started = SharingStarted.WhileSubscribed(5_000), - initialValue = DetailPlantUiState.Initial, - ) + } + .stateIn( + scope = viewModelScope, + started = SharingStarted.WhileSubscribed(5_000), + initialValue = DetailPlantUiState.Initial, + ) fun updateAlarm(alarm: Alarm) { updateAlarmUseCase(alarm).launchIn(viewModelScope) @@ -67,10 +69,7 @@ sealed interface DetailPlantUiState { data object Initial : DetailPlantUiState - data class Loaded( - val plant: Plant, - val alarms: List, - ) : DetailPlantUiState + data class Loaded(val plant: Plant, val alarms: List) : DetailPlantUiState data object NotFound : DetailPlantUiState } diff --git a/features/plant/src/main/java/com/ujizin/leafy/features/plant/detail/ui/PlantAlarmsContent.kt b/features/plant/src/main/java/com/ujizin/leafy/features/plant/detail/ui/PlantAlarmsContent.kt index e06c4ae2..c66c8e56 100644 --- a/features/plant/src/main/java/com/ujizin/leafy/features/plant/detail/ui/PlantAlarmsContent.kt +++ b/features/plant/src/main/java/com/ujizin/leafy/features/plant/detail/ui/PlantAlarmsContent.kt @@ -36,10 +36,7 @@ fun PlantAlarmsContent( alarms: List, onAlarmChanged: (Alarm) -> Unit, ) { - Column( - modifier = modifier, - horizontalAlignment = Alignment.CenterHorizontally, - ) { + Column(modifier = modifier, horizontalAlignment = Alignment.CenterHorizontally) { Text( modifier = Modifier.fillMaxWidth(), text = stringResource(R.string.alarms).capitalize(), @@ -47,25 +44,21 @@ fun PlantAlarmsContent( ) alarms.forEach { alarm -> PlantAlarmRow( - modifier = Modifier - .fillMaxWidth() - .padding(vertical = 16.dp), + modifier = Modifier.fillMaxWidth().padding(vertical = 16.dp), alarm = alarm, - onCheckedChange = { enabled -> - onAlarmChanged(alarm.copy(enabled = enabled)) - }, + onCheckedChange = { enabled -> onAlarmChanged(alarm.copy(enabled = enabled)) }, ) } -// AnimatedButtonIcon( TODO add new alarm -// modifier = Modifier -// .padding(top = 16.dp) -// .size(64.dp) -// .clip(CircleShape) -// .background(MaterialTheme.colorScheme.secondaryContainer), -// icon = Icons.Add, -// size = 24.dp, -// onClick = {} -// ) + // AnimatedButtonIcon( TODO add new alarm + // modifier = Modifier + // .padding(top = 16.dp) + // .size(64.dp) + // .clip(CircleShape) + // .background(MaterialTheme.colorScheme.secondaryContainer), + // icon = Icons.Add, + // size = 24.dp, + // onClick = {} + // ) } } @@ -83,15 +76,10 @@ private fun PlantAlarmRow( ) { val context = LocalContext.current var checked by remember(alarm.enabled) { mutableStateOf(alarm.enabled) } - val alphaRow by animateFloatAsState( - targetValue = if (checked) 1F else 0.5F, - label = "PlantAlarmRow", - ) + val alphaRow by + animateFloatAsState(targetValue = if (checked) 1F else 0.5F, label = "PlantAlarmRow") Row( - modifier = Modifier - .fillMaxSize() - .padding(24.dp) - .alpha(alphaRow), + modifier = Modifier.fillMaxSize().padding(24.dp).alpha(alphaRow), horizontalArrangement = Arrangement.SpaceBetween, verticalAlignment = Alignment.CenterVertically, ) { @@ -107,10 +95,13 @@ private fun PlantAlarmRow( color = MaterialTheme.colorScheme.onSecondaryContainer, ) } - Switch(checked = checked, onCheckedChange = { enabled -> - checked = enabled - onCheckedChange(enabled) - }) + Switch( + checked = checked, + onCheckedChange = { enabled -> + checked = enabled + onCheckedChange(enabled) + }, + ) } } } diff --git a/features/plant/src/main/java/com/ujizin/leafy/features/plant/detail/ui/PlantContent.kt b/features/plant/src/main/java/com/ujizin/leafy/features/plant/detail/ui/PlantContent.kt index 6d417a87..c375c521 100644 --- a/features/plant/src/main/java/com/ujizin/leafy/features/plant/detail/ui/PlantContent.kt +++ b/features/plant/src/main/java/com/ujizin/leafy/features/plant/detail/ui/PlantContent.kt @@ -24,34 +24,26 @@ fun PlantContent( onSharedClick: () -> Unit, ) { Column(modifier) { - Box( - modifier = Modifier.fillMaxWidth(), - ) { + Box(modifier = Modifier.fillMaxWidth()) { Text( modifier = Modifier.padding(end = 16.dp), text = title, style = MaterialTheme.typography.titleMedium, ) PlantActions( - modifier = Modifier - .absoluteOffset(y = -(48.dp)) - .padding(end = 8.dp) - .align(Alignment.TopEnd), + modifier = + Modifier.absoluteOffset(y = -(48.dp)) + .padding(end = 8.dp) + .align(Alignment.TopEnd), onSharedClick = onSharedClick, ) } - Text( - modifier = Modifier.padding(top = 16.dp), - text = description, - ) + Text(modifier = Modifier.padding(top = 16.dp), text = description) } } @Composable -private fun PlantActions( - modifier: Modifier = Modifier, - onSharedClick: () -> Unit, -) { +private fun PlantActions(modifier: Modifier = Modifier, onSharedClick: () -> Unit) { Row(modifier) { AnimatedButtonIcon( icon = Icons.Shared, @@ -59,11 +51,11 @@ private fun PlantActions( onClick = onSharedClick, animation = Animation.SlideToTop, ) -// AnimatedButtonIcon( -// icon = Icons.Favorite, -// size = 24.dp, -// onClick = { }, -// animation = Animation.SlideToTop -// ) + // AnimatedButtonIcon( + // icon = Icons.Favorite, + // size = 24.dp, + // onClick = { }, + // animation = Animation.SlideToTop + // ) } } diff --git a/features/plant/src/main/java/com/ujizin/leafy/features/plant/detail/ui/PlantDetails.kt b/features/plant/src/main/java/com/ujizin/leafy/features/plant/detail/ui/PlantDetails.kt index fd0bc51c..0c4ac0a4 100644 --- a/features/plant/src/main/java/com/ujizin/leafy/features/plant/detail/ui/PlantDetails.kt +++ b/features/plant/src/main/java/com/ujizin/leafy/features/plant/detail/ui/PlantDetails.kt @@ -16,10 +16,7 @@ import com.ujizin.leafy.features.plant.detail.DetailPlantUiState import com.ujizin.leafy.features.plant.detail.DetailPlantViewModel @Composable -fun PlantDetailsRoute( - onBackPressed: OnClick, - viewModel: DetailPlantViewModel = hiltViewModel(), -) { +fun PlantDetailsRoute(onBackPressed: OnClick, viewModel: DetailPlantViewModel = hiltViewModel()) { val context = LocalContext.current val uiState by viewModel.uiState.collectAsStateWithLifecycle() @@ -27,9 +24,7 @@ fun PlantDetailsRoute( onBackPressed = onBackPressed, uiState = uiState, onAlarmChanged = viewModel::updateAlarm, - onDeleteClick = { plant -> - viewModel.deletePlant(plant, onBackPressed) - }, + onDeleteClick = { plant -> viewModel.deletePlant(plant, onBackPressed) }, onSharedClick = { plant -> plant.share(context) }, ) } @@ -45,14 +40,15 @@ private fun PlantDetailsContent( when (val result: DetailPlantUiState = uiState) { DetailPlantUiState.Initial -> PlantDetailsLoading() DetailPlantUiState.NotFound -> PlantDetailsNotFound() - is DetailPlantUiState.Loaded -> PlantDetailsContent( - onBackPressed = onBackPressed, - plant = result.plant, - alarms = result.alarms, - onSharedClick = onSharedClick, - onAlarmChanged = onAlarmChanged, - onDeleteClick = onDeleteClick, - ) + is DetailPlantUiState.Loaded -> + PlantDetailsContent( + onBackPressed = onBackPressed, + plant = result.plant, + alarms = result.alarms, + onSharedClick = onSharedClick, + onAlarmChanged = onAlarmChanged, + onDeleteClick = onDeleteClick, + ) } } @@ -63,16 +59,11 @@ private fun PlantDetailsPreview() { Surface { PlantDetailsContent( onBackPressed = {}, - uiState = DetailPlantUiState.Loaded( - Plant( - 1, - "Plant foo", - "Description", - "foo", - false, + uiState = + DetailPlantUiState.Loaded( + Plant(1, "Plant foo", "Description", "foo", false), + alarms = listOf(), ), - alarms = listOf(), - ), onAlarmChanged = {}, onDeleteClick = {}, onSharedClick = {}, diff --git a/features/plant/src/main/java/com/ujizin/leafy/features/plant/detail/ui/PlantDetailsContent.kt b/features/plant/src/main/java/com/ujizin/leafy/features/plant/detail/ui/PlantDetailsContent.kt index 7fd41cb8..9d6d7fb3 100644 --- a/features/plant/src/main/java/com/ujizin/leafy/features/plant/detail/ui/PlantDetailsContent.kt +++ b/features/plant/src/main/java/com/ujizin/leafy/features/plant/detail/ui/PlantDetailsContent.kt @@ -54,17 +54,11 @@ internal fun PlantDetailsContent( ) }, ) - }, + } ) { - Column( - Modifier - .fillMaxSize() - .verticalScroll(rememberScrollState()), - ) { + Column(Modifier.fillMaxSize().verticalScroll(rememberScrollState())) { CardImage( - modifier = Modifier - .fillMaxWidth() - .aspectRatio(1F), + modifier = Modifier.fillMaxWidth().aspectRatio(1F), animation = Animation.SlideToTop, data = plant.filePath, elevation = 0.dp, @@ -72,12 +66,12 @@ internal fun PlantDetailsContent( contentDescription = plant.title, ) PlantColumn( - modifier = Modifier - .absoluteOffset(y = (-24).dp) - .background( - MaterialTheme.colorScheme.background, - RoundedCornerShape(topStart = 24.dp, topEnd = 24.dp), - ), + modifier = + Modifier.absoluteOffset(y = (-24).dp) + .background( + MaterialTheme.colorScheme.background, + RoundedCornerShape(topStart = 24.dp, topEnd = 24.dp), + ), plant = plant, alarms = alarms, onAlarmChanged = onAlarmChanged, @@ -97,18 +91,14 @@ fun PlantColumn( ) { Column(modifier = modifier) { PlantContent( - modifier = Modifier - .fillMaxWidth() - .paddingScreen(vertical = 24.dp), + modifier = Modifier.fillMaxWidth().paddingScreen(vertical = 24.dp), title = plant.title.capitalize(), onSharedClick = { onSharedClick(plant) }, description = plant.description.capitalize(), ) HorizontalDivider(modifier = Modifier.paddingScreen()) PlantAlarmsContent( - modifier = Modifier - .fillMaxWidth() - .paddingScreen(vertical = 32.dp), + modifier = Modifier.fillMaxWidth().paddingScreen(vertical = 32.dp), alarms = alarms, onAlarmChanged = onAlarmChanged, ) diff --git a/features/plant/src/main/java/com/ujizin/leafy/features/plant/detail/ui/PlantDetailsLoading.kt b/features/plant/src/main/java/com/ujizin/leafy/features/plant/detail/ui/PlantDetailsLoading.kt index ede75844..b04d0585 100644 --- a/features/plant/src/main/java/com/ujizin/leafy/features/plant/detail/ui/PlantDetailsLoading.kt +++ b/features/plant/src/main/java/com/ujizin/leafy/features/plant/detail/ui/PlantDetailsLoading.kt @@ -9,10 +9,7 @@ import androidx.compose.ui.Modifier @Composable internal fun PlantDetailsLoading() { - Box( - modifier = Modifier.fillMaxSize(), - contentAlignment = Alignment.Center, - ) { + Box(modifier = Modifier.fillMaxSize(), contentAlignment = Alignment.Center) { CircularProgressIndicator() } } diff --git a/features/plant/src/main/java/com/ujizin/leafy/features/plant/detail/ui/PlantDetailsTopAppBar.kt b/features/plant/src/main/java/com/ujizin/leafy/features/plant/detail/ui/PlantDetailsTopAppBar.kt index 819718ef..b1c8b197 100644 --- a/features/plant/src/main/java/com/ujizin/leafy/features/plant/detail/ui/PlantDetailsTopAppBar.kt +++ b/features/plant/src/main/java/com/ujizin/leafy/features/plant/detail/ui/PlantDetailsTopAppBar.kt @@ -40,9 +40,7 @@ internal fun PlantDropDown( onExpandedChanged = { isExpanded = it }, ) { DropdownMenuItem( - text = { - Text(stringResource(R.string.delete).capitalize()) - }, + text = { Text(stringResource(R.string.delete).capitalize()) }, onClick = { isExpanded = false showDeleteModal = true @@ -55,9 +53,7 @@ internal fun PlantDropDown( onModalStateChanged = { showDeleteModal = it }, content = { WarningContent( - modifier = Modifier - .paddingScreen() - .padding(bottom = 24.dp), + modifier = Modifier.paddingScreen().padding(bottom = 24.dp), title = stringResource(R.string.warning_delete_title), text = stringResource(R.string.warning_delete_text), onDismissText = stringResource(R.string.warning_delete_dismiss), diff --git a/features/plant/src/main/java/com/ujizin/leafy/features/plant/edit/PlantEditUiState.kt b/features/plant/src/main/java/com/ujizin/leafy/features/plant/edit/PlantEditUiState.kt index 350de2b5..4e745f19 100644 --- a/features/plant/src/main/java/com/ujizin/leafy/features/plant/edit/PlantEditUiState.kt +++ b/features/plant/src/main/java/com/ujizin/leafy/features/plant/edit/PlantEditUiState.kt @@ -9,30 +9,29 @@ import com.ujizin.leafy.domain.model.Plant import com.ujizin.leafy.domain.result.mapResult import com.ujizin.leafy.domain.usecase.plant.load.LoadPlantUseCase import dagger.hilt.android.lifecycle.HiltViewModel +import javax.inject.Inject import kotlinx.coroutines.flow.MutableStateFlow import kotlinx.coroutines.flow.asStateFlow import kotlinx.coroutines.flow.launchIn import kotlinx.coroutines.flow.onEach import kotlinx.coroutines.flow.update -import javax.inject.Inject @HiltViewModel -class PlantEditViewModel @Inject constructor( - savedStateHandle: SavedStateHandle, - private val loadPlant: LoadPlantUseCase, -) : ViewModel() { +class PlantEditViewModel +@Inject +constructor(savedStateHandle: SavedStateHandle, private val loadPlant: LoadPlantUseCase) : + ViewModel() { private val plantId: Long = savedStateHandle.toRoute().plantId private val _uiState = MutableStateFlow(PlantEditUiState.Initial) - val uiState get() = _uiState.asStateFlow() + val uiState + get() = _uiState.asStateFlow() fun loadEditPlant() { loadPlant(plantId) .mapResult() - .onEach { plant -> - _uiState.update { PlantEditUiState.Success(plant) } - } + .onEach { plant -> _uiState.update { PlantEditUiState.Success(plant) } } .launchIn(viewModelScope) } } diff --git a/features/plant/src/main/java/com/ujizin/leafy/features/plant/edit/ui/PlantEdit.kt b/features/plant/src/main/java/com/ujizin/leafy/features/plant/edit/ui/PlantEdit.kt index 6b306f47..e8b15eaf 100644 --- a/features/plant/src/main/java/com/ujizin/leafy/features/plant/edit/ui/PlantEdit.kt +++ b/features/plant/src/main/java/com/ujizin/leafy/features/plant/edit/ui/PlantEdit.kt @@ -10,23 +10,12 @@ import com.ujizin.leafy.features.plant.edit.PlantEditUiState import com.ujizin.leafy.features.plant.edit.PlantEditViewModel @Composable -fun PlantEditRoute( - onBackPressed: OnClick, - viewModel: PlantEditViewModel = hiltViewModel(), -) { +fun PlantEditRoute(onBackPressed: OnClick, viewModel: PlantEditViewModel = hiltViewModel()) { val uiState by viewModel.uiState.collectAsStateWithLifecycle() LaunchedEffect(viewModel) { viewModel.loadEditPlant() } - PlantEdit( - uiState = uiState, - onBackPressed = onBackPressed, - ) + PlantEdit(uiState = uiState, onBackPressed = onBackPressed) } -@Composable -private fun PlantEdit( - uiState: PlantEditUiState, - onBackPressed: OnClick, -) { -} +@Composable private fun PlantEdit(uiState: PlantEditUiState, onBackPressed: OnClick) {} diff --git a/features/preferences/build.gradle.kts b/features/preferences/build.gradle.kts index ccc640f2..23d79d61 100644 --- a/features/preferences/build.gradle.kts +++ b/features/preferences/build.gradle.kts @@ -1,19 +1,5 @@ -plugins { - alias(libs.plugins.android.library) - alias(libs.plugins.kotlin.android) -} +plugins { id("com.ujizin.android-feature") } -apply(from = "$rootDir/config-compose.gradle") -apply(from = "$rootDir/config-android.gradle") +android { namespace = "com.ujizin.leafy.features.preferences" } -android { - namespace = "com.ujizin.leafy.features.preferences" -} - -dependencies { - implementation(projects.core.navigation) - implementation(projects.core.ui) - implementation(projects.domain) - - implementation(libs.google.review) -} +dependencies { implementation(libs.google.review) } diff --git a/features/preferences/src/main/java/com/ujizin/leafy/preferences/PreferencesViewModel.kt b/features/preferences/src/main/java/com/ujizin/leafy/preferences/PreferencesViewModel.kt index b7b64bb6..e499c387 100644 --- a/features/preferences/src/main/java/com/ujizin/leafy/preferences/PreferencesViewModel.kt +++ b/features/preferences/src/main/java/com/ujizin/leafy/preferences/PreferencesViewModel.kt @@ -5,13 +5,12 @@ import androidx.lifecycle.viewModelScope import com.ujizin.leafy.domain.model.User import com.ujizin.leafy.domain.usecase.user.update.UpdateUserUseCase import dagger.hilt.android.lifecycle.HiltViewModel -import kotlinx.coroutines.flow.launchIn import javax.inject.Inject +import kotlinx.coroutines.flow.launchIn @HiltViewModel -class PreferencesViewModel @Inject constructor( - private val updateUser: UpdateUserUseCase, -) : ViewModel() { +class PreferencesViewModel @Inject constructor(private val updateUser: UpdateUserUseCase) : + ViewModel() { fun update(user: User) { updateUser(user).launchIn(viewModelScope) diff --git a/features/preferences/src/main/java/com/ujizin/leafy/preferences/extensions/LanguageExtensions.kt b/features/preferences/src/main/java/com/ujizin/leafy/preferences/extensions/LanguageExtensions.kt index 33bb047f..ee3d5bd1 100644 --- a/features/preferences/src/main/java/com/ujizin/leafy/preferences/extensions/LanguageExtensions.kt +++ b/features/preferences/src/main/java/com/ujizin/leafy/preferences/extensions/LanguageExtensions.kt @@ -6,7 +6,8 @@ import com.ujizin.leafy.features.preferences.R val Language.displayResId: Int @StringRes - get() = when (this) { - Language.PT -> R.string.portuguese - Language.EN -> R.string.english - } + get() = + when (this) { + Language.PT -> R.string.portuguese + Language.EN -> R.string.english + } diff --git a/features/preferences/src/main/java/com/ujizin/leafy/preferences/extensions/ThemeExtensions.kt b/features/preferences/src/main/java/com/ujizin/leafy/preferences/extensions/ThemeExtensions.kt index c016d587..1d6359ab 100644 --- a/features/preferences/src/main/java/com/ujizin/leafy/preferences/extensions/ThemeExtensions.kt +++ b/features/preferences/src/main/java/com/ujizin/leafy/preferences/extensions/ThemeExtensions.kt @@ -6,8 +6,9 @@ import com.ujizin.leafy.features.preferences.R val Theme.displayResId: Int @StringRes - get() = when (this) { - Theme.System -> R.string.system - Theme.Dark -> R.string.dark - Theme.Light -> R.string.light - } + get() = + when (this) { + Theme.System -> R.string.system + Theme.Dark -> R.string.dark + Theme.Light -> R.string.light + } diff --git a/features/preferences/src/main/java/com/ujizin/leafy/preferences/model/PreferenceLanguage.kt b/features/preferences/src/main/java/com/ujizin/leafy/preferences/model/PreferenceLanguage.kt index f86b2a8b..0953c571 100644 --- a/features/preferences/src/main/java/com/ujizin/leafy/preferences/model/PreferenceLanguage.kt +++ b/features/preferences/src/main/java/com/ujizin/leafy/preferences/model/PreferenceLanguage.kt @@ -4,11 +4,7 @@ import android.content.Context import com.ujizin.leafy.domain.model.Language import com.ujizin.leafy.preferences.extensions.displayResId -data class PreferenceLanguage( - val language: Language, - val displayName: String, -) +data class PreferenceLanguage(val language: Language, val displayName: String) -fun getLanguages(context: Context) = Language.entries.map { - PreferenceLanguage(it, context.getString(it.displayResId)) -} +fun getLanguages(context: Context) = + Language.entries.map { PreferenceLanguage(it, context.getString(it.displayResId)) } diff --git a/features/preferences/src/main/java/com/ujizin/leafy/preferences/ui/DynamicColorRow.kt b/features/preferences/src/main/java/com/ujizin/leafy/preferences/ui/DynamicColorRow.kt index 7d7894a5..45fa3bf3 100644 --- a/features/preferences/src/main/java/com/ujizin/leafy/preferences/ui/DynamicColorRow.kt +++ b/features/preferences/src/main/java/com/ujizin/leafy/preferences/ui/DynamicColorRow.kt @@ -28,9 +28,6 @@ fun DynamicColorRow( style = MaterialTheme.typography.titleSmall, ) - Switch( - checked = dynamicColor, - onCheckedChange = onDynamicColorChanged, - ) + Switch(checked = dynamicColor, onCheckedChange = onDynamicColorChanged) } } diff --git a/features/preferences/src/main/java/com/ujizin/leafy/preferences/ui/LanguageSelector.kt b/features/preferences/src/main/java/com/ujizin/leafy/preferences/ui/LanguageSelector.kt index 017cc8ab..cd4934be 100644 --- a/features/preferences/src/main/java/com/ujizin/leafy/preferences/ui/LanguageSelector.kt +++ b/features/preferences/src/main/java/com/ujizin/leafy/preferences/ui/LanguageSelector.kt @@ -31,22 +31,18 @@ fun LanguageSelector( subTitle = stringResource(language.displayResId), ) { val context = LocalContext.current - val languages = remember(language) { - getLanguages(context).map { - ModalValue(it.displayName, it.language) + val languages = + remember(language) { + getLanguages(context).map { ModalValue(it.displayName, it.language) } } - } - val currentLanguage = remember(language) { - ModalValue(context.getString(language.displayResId), language) - } + val currentLanguage = + remember(language) { ModalValue(context.getString(language.displayResId), language) } ModalSelector( title = stringResource(R.string.language), currentValue = currentLanguage, values = languages, - onValueChanged = { language -> - onLanguageChanged(language.value) - }, + onValueChanged = { language -> onLanguageChanged(language.value) }, ) } } diff --git a/features/preferences/src/main/java/com/ujizin/leafy/preferences/ui/Preferences.kt b/features/preferences/src/main/java/com/ujizin/leafy/preferences/ui/Preferences.kt index 61b136e5..df75dafe 100644 --- a/features/preferences/src/main/java/com/ujizin/leafy/preferences/ui/Preferences.kt +++ b/features/preferences/src/main/java/com/ujizin/leafy/preferences/ui/Preferences.kt @@ -28,13 +28,8 @@ import com.ujizin.leafy.preferences.PreferencesViewModel import com.ujizin.leafy.preferences.utils.rememberGoogleReview @Composable -internal fun PreferencesRoute( - viewModel: PreferencesViewModel = hiltViewModel(), -) { - Section( - modifier = Modifier.fillMaxSize(), - title = stringResource(R.string.preferences_title), - ) { +internal fun PreferencesRoute(viewModel: PreferencesViewModel = hiltViewModel()) { + Section(modifier = Modifier.fillMaxSize(), title = stringResource(R.string.preferences_title)) { val user = LocalUser.current Spacer(Modifier.height(16.dp)) @@ -64,46 +59,32 @@ internal fun PreferencesContent( val googleReviewState = rememberGoogleReview() val context = LocalContext.current UserSelector( - modifier = Modifier - .fillMaxWidth() - .paddingScreen(vertical = 16.dp), + modifier = Modifier.fillMaxWidth().paddingScreen(vertical = 16.dp), nickname = user.nickname, onNicknameChanged = onNicknameChanged, ) LanguageSelector( - modifier = Modifier - .fillMaxWidth() - .paddingScreen(vertical = 16.dp), + modifier = Modifier.fillMaxWidth().paddingScreen(vertical = 16.dp), language = user.settings.language, onLanguageChanged = onLanguageChanged, ) ThemeSelector( - modifier = Modifier - .fillMaxWidth() - .paddingScreen(vertical = 16.dp), + modifier = Modifier.fillMaxWidth().paddingScreen(vertical = 16.dp), theme = user.settings.theme, onThemeChanged = onThemeChanged, ) ButtonRow( - modifier = Modifier - .fillMaxWidth() - .paddingScreen(vertical = 16.dp), + modifier = Modifier.fillMaxWidth().paddingScreen(vertical = 16.dp), title = stringResource(R.string.rate_app), subTitle = context.versionName?.let { stringResource(R.string.version, it) }, onClick = { googleReviewState.launch(context) }, ) if (isDynamicColorAvailable) { - HorizontalDivider( - modifier = Modifier - .fillMaxWidth() - .paddingScreen(vertical = 16.dp), - ) + HorizontalDivider(modifier = Modifier.fillMaxWidth().paddingScreen(vertical = 16.dp)) DynamicColorRow( - modifier = Modifier - .fillMaxWidth() - .paddingScreen(), + modifier = Modifier.fillMaxWidth().paddingScreen(), dynamicColor = user.settings.dynamicColor, onDynamicColorChanged = onDynamicColorChanged, ) diff --git a/features/preferences/src/main/java/com/ujizin/leafy/preferences/ui/ThemeSelector.kt b/features/preferences/src/main/java/com/ujizin/leafy/preferences/ui/ThemeSelector.kt index 996868ab..5cc9b7ff 100644 --- a/features/preferences/src/main/java/com/ujizin/leafy/preferences/ui/ThemeSelector.kt +++ b/features/preferences/src/main/java/com/ujizin/leafy/preferences/ui/ThemeSelector.kt @@ -17,19 +17,13 @@ import com.ujizin.leafy.features.preferences.R import com.ujizin.leafy.preferences.extensions.displayResId @Composable -fun ThemeSelector( - modifier: Modifier = Modifier, - theme: Theme, - onThemeChanged: (Theme) -> Unit, -) { +fun ThemeSelector(modifier: Modifier = Modifier, theme: Theme, onThemeChanged: (Theme) -> Unit) { val context = LocalContext.current var showModal by remember { mutableStateOf(false) } val themes = remember { Theme.entries.map { ModalValue(context.getString(it.displayResId), it) } } - val currentTheme = remember(theme) { - ModalValue(context.getString(theme.displayResId), theme) - } + val currentTheme = remember(theme) { ModalValue(context.getString(theme.displayResId), theme) } Selector( modifier = modifier, diff --git a/features/preferences/src/main/java/com/ujizin/leafy/preferences/ui/UserSelector.kt b/features/preferences/src/main/java/com/ujizin/leafy/preferences/ui/UserSelector.kt index 74f0737b..952016b9 100644 --- a/features/preferences/src/main/java/com/ujizin/leafy/preferences/ui/UserSelector.kt +++ b/features/preferences/src/main/java/com/ujizin/leafy/preferences/ui/UserSelector.kt @@ -35,11 +35,7 @@ fun UserSelector( onModalStateChanged = { showModal = it }, ) { UserTextField( - modifier = Modifier.padding( - start = 20.dp, - end = 20.dp, - bottom = 20.dp, - ), + modifier = Modifier.padding(start = 20.dp, end = 20.dp, bottom = 20.dp), label = stringResource(R.string.nickname).capitalize(), nickname = nickname, onSaveNickname = { nickname -> @@ -62,17 +58,13 @@ fun UserTextField( Text(text = label, style = MaterialTheme.typography.titleMedium) TextField( - modifier = Modifier - .fillMaxWidth() - .padding(top = 16.dp), + modifier = Modifier.fillMaxWidth().padding(top = 16.dp), value = newNickname, placeholder = { Placeholder(text = nickname) }, onValueChange = { newNickname = it }, ) Button( - modifier = Modifier - .fillMaxWidth() - .padding(top = 16.dp), + modifier = Modifier.fillMaxWidth().padding(top = 16.dp), text = stringResource(R.string.update), onClick = { onSaveNickname(newNickname) }, ) diff --git a/features/preferences/src/main/java/com/ujizin/leafy/preferences/utils/GoogleReviewState.kt b/features/preferences/src/main/java/com/ujizin/leafy/preferences/utils/GoogleReviewState.kt index c8de5e16..76bd6b5e 100644 --- a/features/preferences/src/main/java/com/ujizin/leafy/preferences/utils/GoogleReviewState.kt +++ b/features/preferences/src/main/java/com/ujizin/leafy/preferences/utils/GoogleReviewState.kt @@ -16,9 +16,7 @@ import com.google.android.play.core.review.ReviewManager import com.google.android.play.core.review.ReviewManagerFactory import com.ujizin.leafy.core.ui.extensions.openAppInPlayStore -/** - * Prepare google review feature in a state, - * */ +/** Prepare google review feature in a state, */ @Stable class GoogleReviewState( private val reviewManager: ReviewManager, @@ -30,20 +28,19 @@ class GoogleReviewState( val activity = context.getActivity() ?: return context.openAppInPlayStore() when { redirectToPlayStore -> context.openAppInPlayStore() - else -> reviewInfo?.let { - val reviewFlow = reviewManager.launchReviewFlow(activity, reviewInfo) - if (reviewFlow.isComplete) context.openAppInPlayStore() - reviewFlow.addOnCompleteListener { redirectToPlayStore = true } - } + else -> + reviewInfo?.let { + val reviewFlow = reviewManager.launchReviewFlow(activity, reviewInfo) + if (reviewFlow.isComplete) context.openAppInPlayStore() + reviewFlow.addOnCompleteListener { redirectToPlayStore = true } + } } } } @Composable private fun rememberReviewTask(reviewManager: ReviewManager, onError: () -> Unit): ReviewInfo? { - var reviewInfo: ReviewInfo? by remember { - mutableStateOf(null) - } + var reviewInfo: ReviewInfo? by remember { mutableStateOf(null) } LaunchedEffect(Unit) { reviewManager.requestReviewFlow().addOnCompleteListener { @@ -58,28 +55,23 @@ private fun rememberReviewTask(reviewManager: ReviewManager, onError: () -> Unit fun rememberGoogleReview(): GoogleReviewState { val context = LocalContext.current var redirectToPlayStore by remember { mutableStateOf(false) } - val reviewManager = remember { - ReviewManagerFactory.create(context) - } + val reviewManager = remember { ReviewManagerFactory.create(context) } - val reviewInfo = rememberReviewTask( - reviewManager = reviewManager, - onError = { redirectToPlayStore = true }, - ) + val reviewInfo = + rememberReviewTask(reviewManager = reviewManager, onError = { redirectToPlayStore = true }) - val googleReviewState = remember(reviewManager, reviewInfo, redirectToPlayStore) { - GoogleReviewState(reviewManager, reviewInfo, redirectToPlayStore) - } + val googleReviewState = + remember(reviewManager, reviewInfo, redirectToPlayStore) { + GoogleReviewState(reviewManager, reviewInfo, redirectToPlayStore) + } return googleReviewState } -/** - * Get activity recursively - * based on: https://stackoverflow.com/a/68423182/11903815 - * */ -fun Context.getActivity(): ComponentActivity? = when (this) { - is ComponentActivity -> this - is ContextWrapper -> baseContext.getActivity() - else -> null -} +/** Get activity recursively based on: https://stackoverflow.com/a/68423182/11903815 */ +fun Context.getActivity(): ComponentActivity? = + when (this) { + is ComponentActivity -> this + is ContextWrapper -> baseContext.getActivity() + else -> null + } diff --git a/features/publish/build.gradle.kts b/features/publish/build.gradle.kts index bec94bd6..8a1b7c13 100644 --- a/features/publish/build.gradle.kts +++ b/features/publish/build.gradle.kts @@ -1,19 +1,5 @@ -plugins { - alias(libs.plugins.android.library) - alias(libs.plugins.kotlin.android) -} +plugins { id("com.ujizin.android-feature") } -apply(from = "$rootDir/config-compose.gradle") -apply(from = "$rootDir/config-android.gradle") +android { namespace = "com.ujizin.leafy.features.publish" } -android { - namespace = "com.ujizin.leafy.features.publish" -} - -dependencies { - implementation(projects.core.navigation) - implementation(projects.core.ui) - implementation(projects.domain) - - implementation(libs.coil) -} +dependencies { implementation(libs.coil) } diff --git a/features/publish/src/main/java/com/ujizin/leafy/publish/PublishGraph.kt b/features/publish/src/main/java/com/ujizin/leafy/publish/PublishGraph.kt index a91a37df..c813cbcf 100644 --- a/features/publish/src/main/java/com/ujizin/leafy/publish/PublishGraph.kt +++ b/features/publish/src/main/java/com/ujizin/leafy/publish/PublishGraph.kt @@ -19,9 +19,6 @@ fun NavGraphBuilder.publishGraph( enterTransition = enterTransition, exitTransition = exitTransition, ) { - PublishRoute( - onBackPressed = onBackPressed, - onFinishPublish = onNextClick, - ) + PublishRoute(onBackPressed = onBackPressed, onFinishPublish = onNextClick) } } diff --git a/features/publish/src/main/java/com/ujizin/leafy/publish/PublishSection.kt b/features/publish/src/main/java/com/ujizin/leafy/publish/PublishSection.kt index 515912c5..cb555966 100644 --- a/features/publish/src/main/java/com/ujizin/leafy/publish/PublishSection.kt +++ b/features/publish/src/main/java/com/ujizin/leafy/publish/PublishSection.kt @@ -48,31 +48,25 @@ fun PublishContent( onNextClicked: (title: String, description: String) -> Unit, ) { Section( - modifier = Modifier - .fillMaxSize() - .verticalScroll(rememberScrollState()), + modifier = Modifier.fillMaxSize().verticalScroll(rememberScrollState()), title = stringResource(R.string.publish_title), subTitle = stringResource(R.string.publish_description), animation = Animation.SlideToTopLargeDuration, - trailingIcon = { - AnimatedButtonIcon(icon = Icons.Back, onClick = onBackPressed) - }, + trailingIcon = { AnimatedButtonIcon(icon = Icons.Back, onClick = onBackPressed) }, ) { var title by rememberSaveable { mutableStateOf("") } var description by rememberSaveable { mutableStateOf("") } TextField( - modifier = Modifier - .fillMaxWidth() - .padding(top = 32.dp, start = 20.dp, end = 20.dp), + modifier = Modifier.fillMaxWidth().padding(top = 32.dp, start = 20.dp, end = 20.dp), placeholder = { Placeholder(text = stringResource(R.string.title)) }, value = title, onValueChange = { title = it }, ) TextField( - modifier = Modifier - .fillMaxWidth() - .aspectRatio(1.75F) - .padding(top = 16.dp, start = 20.dp, end = 20.dp), + modifier = + Modifier.fillMaxWidth() + .aspectRatio(1.75F) + .padding(top = 16.dp, start = 20.dp, end = 20.dp), placeholder = { Placeholder(text = stringResource(R.string.description)) }, singleLine = false, value = description, @@ -80,9 +74,7 @@ fun PublishContent( ) Spacer(modifier = Modifier.weight(1F)) Button( - modifier = Modifier - .fillMaxWidth() - .paddingScreen(vertical = 16.dp), + modifier = Modifier.fillMaxWidth().paddingScreen(vertical = 16.dp), enabled = title.isNotBlank() && description.isNotBlank(), text = stringResource(R.string.next), onClick = { onNextClicked(title, description) }, diff --git a/features/publish/src/main/java/com/ujizin/leafy/publish/viewmodel/PublishViewModel.kt b/features/publish/src/main/java/com/ujizin/leafy/publish/viewmodel/PublishViewModel.kt index b2a602ca..caaf7ad1 100644 --- a/features/publish/src/main/java/com/ujizin/leafy/publish/viewmodel/PublishViewModel.kt +++ b/features/publish/src/main/java/com/ujizin/leafy/publish/viewmodel/PublishViewModel.kt @@ -4,21 +4,17 @@ import androidx.lifecycle.ViewModel import androidx.lifecycle.viewModelScope import com.ujizin.leafy.domain.usecase.plant.add.AddDraftPlantUseCase import dagger.hilt.android.lifecycle.HiltViewModel +import javax.inject.Inject import kotlinx.coroutines.flow.launchIn import kotlinx.coroutines.flow.onCompletion -import javax.inject.Inject @HiltViewModel -class PublishViewModel @Inject constructor( - private val addDraftPlant: AddDraftPlantUseCase, -) : ViewModel() { +class PublishViewModel @Inject constructor(private val addDraftPlant: AddDraftPlantUseCase) : + ViewModel() { fun sendDraftPlant(title: String, description: String, onFinishPublish: () -> Unit) { - addDraftPlant( - title = title, - description = description, - ).onCompletion { - onFinishPublish() - }.launchIn(viewModelScope) + addDraftPlant(title = title, description = description) + .onCompletion { onFinishPublish() } + .launchIn(viewModelScope) } } diff --git a/features/search/build.gradle.kts b/features/search/build.gradle.kts index 8383f0c3..7f671599 100644 --- a/features/search/build.gradle.kts +++ b/features/search/build.gradle.kts @@ -1,19 +1,3 @@ -plugins { - alias(libs.plugins.android.library) - alias(libs.plugins.kotlin.android) -} +plugins { id("com.ujizin.android-feature") } -apply(from = "$rootDir/config-compose.gradle") -apply(from = "$rootDir/config-android.gradle") - -android { - namespace = "com.ujizin.leafy.features.search" -} - -dependencies { - implementation(projects.core.navigation) - implementation(projects.core.ui) - implementation(projects.core.themes) - - implementation(projects.domain) -} +android { namespace = "com.ujizin.leafy.features.search" } diff --git a/features/search/src/main/java/com/ujizin/leafy/search/SearchViewModel.kt b/features/search/src/main/java/com/ujizin/leafy/search/SearchViewModel.kt index 03b0b858..d6544070 100644 --- a/features/search/src/main/java/com/ujizin/leafy/search/SearchViewModel.kt +++ b/features/search/src/main/java/com/ujizin/leafy/search/SearchViewModel.kt @@ -11,16 +11,18 @@ import com.ujizin.leafy.domain.result.Result import com.ujizin.leafy.domain.usecase.plant.find.FindPlantUseCase import com.ujizin.leafy.domain.usecase.plant.load.LoadAllPlantUseCase import dagger.hilt.android.lifecycle.HiltViewModel +import javax.inject.Inject import kotlinx.coroutines.flow.Flow import kotlinx.coroutines.flow.MutableStateFlow import kotlinx.coroutines.flow.asStateFlow import kotlinx.coroutines.flow.launchIn import kotlinx.coroutines.flow.onEach import kotlinx.coroutines.flow.update -import javax.inject.Inject @HiltViewModel -class SearchViewModel @Inject constructor( +class SearchViewModel +@Inject +constructor( savedStateHandle: SavedStateHandle, private val loadPlants: LoadAllPlantUseCase, private val findPlant: FindPlantUseCase, @@ -33,9 +35,11 @@ class SearchViewModel @Inject constructor( fun search(sentence: String) { when { - sentence.isBlank() -> loadPlants() - else -> findPlant(sentence) - }.onEachPlant().launchIn(viewModelScope) + sentence.isBlank() -> loadPlants() + else -> findPlant(sentence) + } + .onEachPlant() + .launchIn(viewModelScope) } private fun Flow>>.onEachPlant() = onEach { result -> @@ -56,12 +60,9 @@ class SearchViewModel @Inject constructor( } sealed class SearchUiState(val items: List) { - @Immutable - data class Initial(val autoFocus: Boolean = false) : SearchUiState(emptyList()) + @Immutable data class Initial(val autoFocus: Boolean = false) : SearchUiState(emptyList()) - @Immutable - data object Empty : SearchUiState(emptyList()) + @Immutable data object Empty : SearchUiState(emptyList()) - @Immutable - data class Loaded(private val data: List) : SearchUiState(data) + @Immutable data class Loaded(private val data: List) : SearchUiState(data) } diff --git a/features/search/src/main/java/com/ujizin/leafy/search/ui/SearchEmptyList.kt b/features/search/src/main/java/com/ujizin/leafy/search/ui/SearchEmptyList.kt index bcc221d5..c3fd9191 100644 --- a/features/search/src/main/java/com/ujizin/leafy/search/ui/SearchEmptyList.kt +++ b/features/search/src/main/java/com/ujizin/leafy/search/ui/SearchEmptyList.kt @@ -4,11 +4,11 @@ import androidx.compose.runtime.Composable import androidx.compose.runtime.remember import androidx.compose.ui.Modifier import androidx.compose.ui.platform.LocalContext +import com.ujizin.leafy.core.components.R as CR import com.ujizin.leafy.core.ui.components.EmptySection import com.ujizin.leafy.core.ui.extensions.OnClick import com.ujizin.leafy.core.ui.extensions.capitalize import com.ujizin.leafy.features.search.R -import com.ujizin.leafy.core.components.R as CR @Composable internal fun SearchEmptyList( @@ -17,17 +17,15 @@ internal fun SearchEmptyList( onTakePictureClick: OnClick, ) { val context = LocalContext.current - val description = remember(searchText) { - if (searchText.isEmpty()) { - context.getString(CR.string.empty_plant) - } else { - context.getString(R.string.search_empty_description, searchText) - } - }.capitalize() + val description = + remember(searchText) { + if (searchText.isEmpty()) { + context.getString(CR.string.empty_plant) + } else { + context.getString(R.string.search_empty_description, searchText) + } + } + .capitalize() - EmptySection( - modifier = modifier, - description = description, - onClick = onTakePictureClick, - ) + EmptySection(modifier = modifier, description = description, onClick = onTakePictureClick) } diff --git a/features/search/src/main/java/com/ujizin/leafy/search/ui/SearchLoading.kt b/features/search/src/main/java/com/ujizin/leafy/search/ui/SearchLoading.kt index b20a8bb3..dd6eb5f5 100644 --- a/features/search/src/main/java/com/ujizin/leafy/search/ui/SearchLoading.kt +++ b/features/search/src/main/java/com/ujizin/leafy/search/ui/SearchLoading.kt @@ -16,15 +16,9 @@ internal fun SearchLoading( focusRequester: FocusRequester, modifier: Modifier = Modifier, ) { - LaunchedEffect(autoFocus) { - if (autoFocus) focusRequester.requestFocus() - } + LaunchedEffect(autoFocus) { if (autoFocus) focusRequester.requestFocus() } Box(modifier = modifier) { - CircularProgressIndicator( - modifier = Modifier - .size(32.dp) - .align(Alignment.Center), - ) + CircularProgressIndicator(modifier = Modifier.size(32.dp).align(Alignment.Center)) } } diff --git a/features/search/src/main/java/com/ujizin/leafy/search/ui/SearchSection.kt b/features/search/src/main/java/com/ujizin/leafy/search/ui/SearchSection.kt index a6ef13dc..07f53a03 100644 --- a/features/search/src/main/java/com/ujizin/leafy/search/ui/SearchSection.kt +++ b/features/search/src/main/java/com/ujizin/leafy/search/ui/SearchSection.kt @@ -89,9 +89,7 @@ private fun SearchContent( ) { item { Section( - modifier = Modifier - .fillMaxWidth() - .paddingScreen(), + modifier = Modifier.fillMaxWidth().paddingScreen(), headerPaddingValues = PaddingValues(top = 32.dp), leadingIcon = if (!isKeyboardOpen) leadingIcon(onDrawerClick) else null, title = stringResource(R.string.search).capitalize(), @@ -100,11 +98,11 @@ private fun SearchContent( stickyHeader { TextField( - modifier = Modifier - .background(MaterialTheme.colorScheme.background) - .fillMaxWidth() - .paddingScreen(vertical = 16.dp) - .focusRequester(focusRequester), + modifier = + Modifier.background(MaterialTheme.colorScheme.background) + .fillMaxWidth() + .paddingScreen(vertical = 16.dp) + .focusRequester(focusRequester), placeholder = { SearchPlaceholder() }, value = searchText, onValueChange = onSearchTextChanged, @@ -112,37 +110,32 @@ private fun SearchContent( } when (val result: SearchUiState = uiState) { - is SearchUiState.Initial -> item { - SearchLoading( - modifier = Modifier - .fillMaxWidth() - .padding(top = 16.dp), - autoFocus = result.autoFocus, - focusRequester = focusRequester, - ) - } + is SearchUiState.Initial -> + item { + SearchLoading( + modifier = Modifier.fillMaxWidth().padding(top = 16.dp), + autoFocus = result.autoFocus, + focusRequester = focusRequester, + ) + } - SearchUiState.Empty -> item { - SearchEmptyList( - modifier = Modifier - .padding(20.dp) - .fillMaxWidth(), - searchText = searchText, - onTakePictureClick = onTakePictureClick, - ) - } + SearchUiState.Empty -> + item { + SearchEmptyList( + modifier = Modifier.padding(20.dp).fillMaxWidth(), + searchText = searchText, + onTakePictureClick = onTakePictureClick, + ) + } - is SearchUiState.Loaded -> searchItems( - modifier = Modifier - .paddingScreen(vertical = 8.dp) - .fillMaxWidth() - .aspectRatio(1F), - data = result.items, - onPlantClick = onPlantClick, - onSharedClick = { plant -> - plant.share(context) - }, - ) + is SearchUiState.Loaded -> + searchItems( + modifier = + Modifier.paddingScreen(vertical = 8.dp).fillMaxWidth().aspectRatio(1F), + data = result.items, + onPlantClick = onPlantClick, + onSharedClick = { plant -> plant.share(context) }, + ) } item { Spacer(Modifier.padding(64.dp)) } } @@ -164,8 +157,8 @@ private fun SearchPreview() { SearchContent( uiState = SearchUiState.Empty, isKeyboardOpen = false, - onDrawerClick = { }, - onTakePictureClick = { }, + onDrawerClick = {}, + onTakePictureClick = {}, searchText = "", focusRequester = remember { FocusRequester() }, onSearchTextChanged = {}, diff --git a/features/search/src/main/java/com/ujizin/leafy/search/ui/components/SearchPlaceholder.kt b/features/search/src/main/java/com/ujizin/leafy/search/ui/components/SearchPlaceholder.kt index a195a4cd..168a22dd 100644 --- a/features/search/src/main/java/com/ujizin/leafy/search/ui/components/SearchPlaceholder.kt +++ b/features/search/src/main/java/com/ujizin/leafy/search/ui/components/SearchPlaceholder.kt @@ -19,9 +19,7 @@ internal fun SearchPlaceholder(modifier: Modifier = Modifier) { modifier = modifier, leadingIcon = { AnimatedIcon( - modifier = Modifier - .padding(end = 8.dp) - .size(24.dp), + modifier = Modifier.padding(end = 8.dp).size(24.dp), tint = MaterialTheme.colorScheme.onBackground.copy(alpha = 0.5F), icon = Icons.Magnifier, ) diff --git a/features/tasks/build.gradle.kts b/features/tasks/build.gradle.kts index df1d4665..bdd3fa33 100644 --- a/features/tasks/build.gradle.kts +++ b/features/tasks/build.gradle.kts @@ -1,18 +1,3 @@ -plugins { - alias(libs.plugins.android.library) - alias(libs.plugins.kotlin.android) -} +plugins { id("com.ujizin.android-feature") } -apply(from = "$rootDir/config-compose.gradle") -apply(from = "$rootDir/config-android.gradle") - -android { - namespace = "com.ujizin.leafy.features.tasks" -} - -dependencies { - implementation(projects.domain) - - implementation(projects.core.navigation) - implementation(projects.core.ui) -} +android { namespace = "com.ujizin.leafy.features.tasks" } diff --git a/features/tasks/src/main/java/com/ujizin/leafy/features/tasks/Tasks.kt b/features/tasks/src/main/java/com/ujizin/leafy/features/tasks/Tasks.kt index 165bd786..97711701 100644 --- a/features/tasks/src/main/java/com/ujizin/leafy/features/tasks/Tasks.kt +++ b/features/tasks/src/main/java/com/ujizin/leafy/features/tasks/Tasks.kt @@ -70,9 +70,7 @@ private fun TasksContent( onPlantClick: (Long) -> Unit, onDrawerClick: OnClick, ) { - LazyColumn( - modifier = Modifier.fillMaxSize(), - ) { + LazyColumn(modifier = Modifier.fillMaxSize()) { item { Section( modifier = Modifier.padding(bottom = 16.dp), @@ -85,28 +83,26 @@ private fun TasksContent( when (uiState) { TasksUiState.Initial -> Unit - TasksUiState.Empty -> item { - EmptySection( - description = stringResource(id = R.string.task_empty_description), - modifier = Modifier.fillMaxWidth(), - onClick = onTakePictureClick, - ) - } - - is TasksUiState.Success -> uiState.tasks.forEach { (weekDay, tasks) -> - stickyHeader { HeaderWeekDay(weekDay) } - items(tasks) { task -> - TaskItems( - modifier = Modifier - .fillMaxWidth() - .paddingScreen(vertical = 16.dp), - task = task, - onClick = { - onPlantClick(task.plant.id) - }, + TasksUiState.Empty -> + item { + EmptySection( + description = stringResource(id = R.string.task_empty_description), + modifier = Modifier.fillMaxWidth(), + onClick = onTakePictureClick, ) } - } + + is TasksUiState.Success -> + uiState.tasks.forEach { (weekDay, tasks) -> + stickyHeader { HeaderWeekDay(weekDay) } + items(tasks) { task -> + TaskItems( + modifier = Modifier.fillMaxWidth().paddingScreen(vertical = 16.dp), + task = task, + onClick = { onPlantClick(task.plant.id) }, + ) + } + } } item { Spacer(Modifier.padding(64.dp)) } @@ -114,24 +110,15 @@ private fun TasksContent( } @Composable -fun TaskItems( - modifier: Modifier = Modifier, - task: Task, - onClick: OnClick, -) { +fun TaskItems(modifier: Modifier = Modifier, task: Task, onClick: OnClick) { Card( modifier = modifier, shape = MaterialTheme.shapes.medium, - elevation = CardDefaults.cardElevation( - pressedElevation = 16.dp, - defaultElevation = 8.dp, - ), + elevation = CardDefaults.cardElevation(pressedElevation = 16.dp, defaultElevation = 8.dp), onClick = onClick, ) { Row( - modifier = Modifier - .fillMaxWidth() - .padding(16.dp), + modifier = Modifier.fillMaxWidth().padding(16.dp), verticalAlignment = Alignment.CenterVertically, horizontalArrangement = Arrangement.SpaceBetween, ) { @@ -141,19 +128,11 @@ fun TaskItems( } @Composable -private fun PlantItem( - modifier: Modifier = Modifier, - task: Task, -) { +private fun PlantItem(modifier: Modifier = Modifier, task: Task) { val context = LocalContext.current - Row( - modifier = modifier, - verticalAlignment = Alignment.CenterVertically, - ) { + Row(modifier = modifier, verticalAlignment = Alignment.CenterVertically) { Image( - modifier = Modifier - .size(80.dp) - .clip(MaterialTheme.shapes.small), + modifier = Modifier.size(80.dp).clip(MaterialTheme.shapes.small), model = task.plant.filePath, contentDescription = task.plant.title, ) @@ -163,10 +142,7 @@ private fun PlantItem( style = MaterialTheme.typography.titleMedium, maxLines = 1, ) - Text( - text = task.alarm.weekDays.getDisplayName(context).capitalize(), - maxLines = 1, - ) + Text(text = task.alarm.weekDays.getDisplayName(context).capitalize(), maxLines = 1) Text( text = task.alarm.dateFormatted, style = MaterialTheme.typography.titleSmall, @@ -181,16 +157,13 @@ private fun PlantItem( @Composable fun HeaderWeekDay(weekDay: WeekDay) { Text( - modifier = Modifier - .fillMaxWidth() - .background(MaterialTheme.colorScheme.background) - .paddingScreen(vertical = 8.dp), + modifier = + Modifier.fillMaxWidth() + .background(MaterialTheme.colorScheme.background) + .paddingScreen(vertical = 8.dp), text = stringResource(id = weekDay.displayNameRes).capitalize(), style = MaterialTheme.typography.titleMedium, ) } -@ThemePreviews -@Composable -private fun TasksPreview() { -} +@ThemePreviews @Composable private fun TasksPreview() {} diff --git a/features/tasks/src/main/java/com/ujizin/leafy/features/tasks/TasksViewModel.kt b/features/tasks/src/main/java/com/ujizin/leafy/features/tasks/TasksViewModel.kt index 12cddbd9..ed72a940 100644 --- a/features/tasks/src/main/java/com/ujizin/leafy/features/tasks/TasksViewModel.kt +++ b/features/tasks/src/main/java/com/ujizin/leafy/features/tasks/TasksViewModel.kt @@ -11,19 +11,19 @@ import com.ujizin.leafy.domain.usecase.plant.load.LoadPlantUseCase import com.ujizin.leafy.features.tasks.model.Task import com.ujizin.leafy.features.tasks.model.TaskWeek import dagger.hilt.android.lifecycle.HiltViewModel +import javax.inject.Inject import kotlinx.coroutines.flow.MutableStateFlow import kotlinx.coroutines.flow.asStateFlow import kotlinx.coroutines.flow.first import kotlinx.coroutines.flow.launchIn import kotlinx.coroutines.flow.onEach import kotlinx.coroutines.flow.update -import javax.inject.Inject @HiltViewModel -class TasksViewModel @Inject constructor( - private val loadAllAlarms: LoadAlarmsUseCase, - private val loadPlant: LoadPlantUseCase, -) : ViewModel() { +class TasksViewModel +@Inject +constructor(private val loadAllAlarms: LoadAlarmsUseCase, private val loadPlant: LoadPlantUseCase) : + ViewModel() { private val _uiState = MutableStateFlow(TasksUiState.Initial) val uiState = _uiState.asStateFlow() @@ -32,24 +32,31 @@ class TasksViewModel @Inject constructor( loadAllAlarms() .mapResult() .onEach { alarms -> - val tasks = WeekDay.entries.reorderByCurrentDay().mapNotNull { weekDay -> - val alarmHasWeekDay = alarms.any { it.weekDays.contains(weekDay) && it.enabled } - when { - alarmHasWeekDay -> TaskWeek( - weekDay = weekDay, - tasks = alarms.filter { - it.enabled && it.weekDays.contains(weekDay) - }.map { alarm -> - Task( - plant = loadPlant(alarm.plantId).mapResult().first(), - alarm = alarm, + val tasks = + WeekDay.entries.reorderByCurrentDay().mapNotNull { weekDay -> + val alarmHasWeekDay = + alarms.any { it.weekDays.contains(weekDay) && it.enabled } + when { + alarmHasWeekDay -> + TaskWeek( + weekDay = weekDay, + tasks = + alarms + .filter { it.enabled && it.weekDays.contains(weekDay) } + .map { alarm -> + Task( + plant = + loadPlant(alarm.plantId) + .mapResult() + .first(), + alarm = alarm, + ) + }, ) - }, - ) - else -> null + else -> null + } } - } _uiState.update { if (tasks.isEmpty()) TasksUiState.Empty else TasksUiState.Success(tasks) @@ -60,12 +67,9 @@ class TasksViewModel @Inject constructor( } sealed interface TasksUiState { - @Immutable - data object Initial : TasksUiState + @Immutable data object Initial : TasksUiState - @Immutable - data object Empty : TasksUiState + @Immutable data object Empty : TasksUiState - @Immutable - data class Success(val tasks: List) : TasksUiState + @Immutable data class Success(val tasks: List) : TasksUiState } diff --git a/features/tasks/src/main/java/com/ujizin/leafy/features/tasks/model/Task.kt b/features/tasks/src/main/java/com/ujizin/leafy/features/tasks/model/Task.kt index 702709ca..dc8c7349 100644 --- a/features/tasks/src/main/java/com/ujizin/leafy/features/tasks/model/Task.kt +++ b/features/tasks/src/main/java/com/ujizin/leafy/features/tasks/model/Task.kt @@ -3,7 +3,4 @@ package com.ujizin.leafy.features.tasks.model import com.ujizin.leafy.domain.model.Alarm import com.ujizin.leafy.domain.model.Plant -data class Task( - val plant: Plant, - val alarm: Alarm, -) +data class Task(val plant: Plant, val alarm: Alarm) diff --git a/features/tasks/src/main/java/com/ujizin/leafy/features/tasks/model/TaskWeek.kt b/features/tasks/src/main/java/com/ujizin/leafy/features/tasks/model/TaskWeek.kt index 423304aa..13a525ce 100644 --- a/features/tasks/src/main/java/com/ujizin/leafy/features/tasks/model/TaskWeek.kt +++ b/features/tasks/src/main/java/com/ujizin/leafy/features/tasks/model/TaskWeek.kt @@ -2,7 +2,4 @@ package com.ujizin.leafy.features.tasks.model import com.ujizin.leafy.domain.model.WeekDay -data class TaskWeek( - val weekDay: WeekDay, - val tasks: List, -) +data class TaskWeek(val weekDay: WeekDay, val tasks: List) diff --git a/gradle/libs.versions.toml b/gradle/libs.versions.toml index 4d556a5e..1628b925 100644 --- a/gradle/libs.versions.toml +++ b/gradle/libs.versions.toml @@ -1,7 +1,7 @@ [versions] kotlin = "1.9.23" -gradle = "8.5.2" +gradle = "8.6.1" compose = "1.7.2" compose-bom = "2024.09.02" compose-compiler = "1.5.13" @@ -10,6 +10,8 @@ material3 = "1.3.0" material = "1.12.0" coroutines = "1.8.1" androidx-core = "1.13.1" +ktfmt = "0.52" +ktfmt-plugin = "0.20.1" splashscreen = "1.0.1" appcompat = "1.7.0" espresso = "3.6.1" @@ -22,15 +24,14 @@ ksp = "1.9.23-1.0.20" navigation-compose = "2.8.1" datastore = "1.1.1" kotlinx-serialization = "1.5.1" -ktlint = "0.48.2" detekt = "1.22.0" coil = "2.7.0" accompanist = "0.34.0" +spotless = "6.25.0" test-runner = "1.6.2" test-core-ktx = "1.6.1" mockk = "1.13.5" camposer = "0.4.0" -spotless = "6.25.0" google-services = "4.4.2" google-review = "2.0.1" firebase-bom = "33.1.2" @@ -40,6 +41,15 @@ firebase-crashlytics = "2.9.9" # Implementations +## Project +gradle-plugin = { module = "com.android.tools.build:gradle", version.ref = "gradle" } +gradle-api-plugin = { module = "com.android.tools.build:gradle-api", version.ref = "gradle" } +kotlin-gradle-plugin = { module = "org.jetbrains.kotlin:kotlin-gradle-plugin", version.ref = "kotlin" } +kfmt-plugin = { module = "com.ncorti.ktfmt.gradle:plugin", version.ref = "ktfmt-plugin" } +spotless-plugin-gradle = { module = "com.diffplug.spotless:spotless-plugin-gradle", version.ref = "spotless" } +hilt-plugin = { module = "com.google.dagger:hilt-android-gradle-plugin", version.ref = "hilt" } +ksp-plugin = { module = "com.google.devtools.ksp:com.google.devtools.ksp.gradle.plugin", version.ref = "ksp" } + androidx-lifecycle = { module = "androidx.lifecycle:lifecycle-runtime-ktx", version.ref = "androidx-lifecyle" } androidx-lifecycle-viewmodel = { module = "androidx.lifecycle:lifecycle-viewmodel-ktx", version.ref = "androidx-lifecyle" } androidx-core = { module = "androidx.core:core", version.ref = "androidx-core" } @@ -104,8 +114,6 @@ androidx-espresso = { module = "androidx.test.espresso:espresso-core", version.r android-junit = { module = "androidx.test.ext:junit", version.ref = "android-junit" } compose-android-test = { module = "androidx.compose.ui:ui-test-junit4", version.ref = "compose" } -ktlint = { module = "com.pinterest:ktlint", version.ref = "ktlint" } - [bundles] androidx = [ @@ -145,13 +153,10 @@ datastore = [ [plugins] -android-application = { id = "com.android.application", version.ref = "gradle" } android-library = { id = "com.android.library", version.ref = "gradle" } kotlin-android = { id = "org.jetbrains.kotlin.android", version.ref = "kotlin" } kotlinx-serialization = { id = "org.jetbrains.kotlin.plugin.serialization", version.ref = "kotlin" } ksp = { id = "com.google.devtools.ksp", version.ref = "ksp" } -hilt = { id = "com.google.dagger.hilt.android", version.ref = "hilt" } detekt = { id = "io.gitlab.arturbosch.detekt", version.ref = "detekt" } -spotless = { id = "com.diffplug.spotless", version.ref = "spotless" } google-services = { id = "com.google.gms.google-services" } google-crashlytics = { id = "com.google.firebase.crashlytics" } \ No newline at end of file diff --git a/gradle/wrapper/gradle-wrapper.jar b/gradle/wrapper/gradle-wrapper.jar index e708b1c0..e6441136 100644 Binary files a/gradle/wrapper/gradle-wrapper.jar and b/gradle/wrapper/gradle-wrapper.jar differ diff --git a/gradle/wrapper/gradle-wrapper.properties b/gradle/wrapper/gradle-wrapper.properties index 13246c79..df97d72b 100644 --- a/gradle/wrapper/gradle-wrapper.properties +++ b/gradle/wrapper/gradle-wrapper.properties @@ -1,6 +1,7 @@ -#Mon Mar 14 19:20:20 BRT 2022 distributionBase=GRADLE_USER_HOME -distributionUrl=https\://services.gradle.org/distributions/gradle-8.7-bin.zip distributionPath=wrapper/dists -zipStorePath=wrapper/dists +distributionUrl=https\://services.gradle.org/distributions/gradle-8.10.2-bin.zip +networkTimeout=10000 +validateDistributionUrl=true zipStoreBase=GRADLE_USER_HOME +zipStorePath=wrapper/dists diff --git a/gradlew b/gradlew index 4f906e0c..1aa94a42 100755 --- a/gradlew +++ b/gradlew @@ -1,7 +1,7 @@ -#!/usr/bin/env sh +#!/bin/sh # -# Copyright 2015 the original author or authors. +# Copyright © 2015-2021 the original authors. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. @@ -17,67 +17,99 @@ # ############################################################################## -## -## Gradle start up script for UN*X -## +# +# Gradle start up script for POSIX generated by Gradle. +# +# Important for running: +# +# (1) You need a POSIX-compliant shell to run this script. If your /bin/sh is +# noncompliant, but you have some other compliant shell such as ksh or +# bash, then to run this script, type that shell name before the whole +# command line, like: +# +# ksh Gradle +# +# Busybox and similar reduced shells will NOT work, because this script +# requires all of these POSIX shell features: +# * functions; +# * expansions «$var», «${var}», «${var:-default}», «${var+SET}», +# «${var#prefix}», «${var%suffix}», and «$( cmd )»; +# * compound commands having a testable exit status, especially «case»; +# * various built-in commands including «command», «set», and «ulimit». +# +# Important for patching: +# +# (2) This script targets any POSIX shell, so it avoids extensions provided +# by Bash, Ksh, etc; in particular arrays are avoided. +# +# The "traditional" practice of packing multiple parameters into a +# space-separated string is a well documented source of bugs and security +# problems, so this is (mostly) avoided, by progressively accumulating +# options in "$@", and eventually passing that to Java. +# +# Where the inherited environment variables (DEFAULT_JVM_OPTS, JAVA_OPTS, +# and GRADLE_OPTS) rely on word-splitting, this is performed explicitly; +# see the in-line comments for details. +# +# There are tweaks for specific operating systems such as AIX, CygWin, +# Darwin, MinGW, and NonStop. +# +# (3) This script is generated from the Groovy template +# https://github.com/gradle/gradle/blob/HEAD/subprojects/plugins/src/main/resources/org/gradle/api/internal/plugins/unixStartScript.txt +# within the Gradle project. +# +# You can find Gradle at https://github.com/gradle/gradle/. +# ############################################################################## # Attempt to set APP_HOME + # Resolve links: $0 may be a link -PRG="$0" -# Need this for relative symlinks. -while [ -h "$PRG" ] ; do - ls=`ls -ld "$PRG"` - link=`expr "$ls" : '.*-> \(.*\)$'` - if expr "$link" : '/.*' > /dev/null; then - PRG="$link" - else - PRG=`dirname "$PRG"`"/$link" - fi +app_path=$0 + +# Need this for daisy-chained symlinks. +while + APP_HOME=${app_path%"${app_path##*/}"} # leaves a trailing /; empty if no leading path + [ -h "$app_path" ] +do + ls=$( ls -ld "$app_path" ) + link=${ls#*' -> '} + case $link in #( + /*) app_path=$link ;; #( + *) app_path=$APP_HOME$link ;; + esac done -SAVED="`pwd`" -cd "`dirname \"$PRG\"`/" >/dev/null -APP_HOME="`pwd -P`" -cd "$SAVED" >/dev/null -APP_NAME="Gradle" -APP_BASE_NAME=`basename "$0"` - -# Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script. -DEFAULT_JVM_OPTS='"-Xmx64m" "-Xms64m"' +# This is normally unused +# shellcheck disable=SC2034 +APP_BASE_NAME=${0##*/} +# Discard cd standard output in case $CDPATH is set (https://github.com/gradle/gradle/issues/25036) +APP_HOME=$( cd "${APP_HOME:-./}" > /dev/null && pwd -P ) || exit # Use the maximum available, or set MAX_FD != -1 to use that value. -MAX_FD="maximum" +MAX_FD=maximum warn () { echo "$*" -} +} >&2 die () { echo echo "$*" echo exit 1 -} +} >&2 # OS specific support (must be 'true' or 'false'). cygwin=false msys=false darwin=false nonstop=false -case "`uname`" in - CYGWIN* ) - cygwin=true - ;; - Darwin* ) - darwin=true - ;; - MINGW* ) - msys=true - ;; - NONSTOP* ) - nonstop=true - ;; +case "$( uname )" in #( + CYGWIN* ) cygwin=true ;; #( + Darwin* ) darwin=true ;; #( + MSYS* | MINGW* ) msys=true ;; #( + NONSTOP* ) nonstop=true ;; esac CLASSPATH=$APP_HOME/gradle/wrapper/gradle-wrapper.jar @@ -87,9 +119,9 @@ CLASSPATH=$APP_HOME/gradle/wrapper/gradle-wrapper.jar if [ -n "$JAVA_HOME" ] ; then if [ -x "$JAVA_HOME/jre/sh/java" ] ; then # IBM's JDK on AIX uses strange locations for the executables - JAVACMD="$JAVA_HOME/jre/sh/java" + JAVACMD=$JAVA_HOME/jre/sh/java else - JAVACMD="$JAVA_HOME/bin/java" + JAVACMD=$JAVA_HOME/bin/java fi if [ ! -x "$JAVACMD" ] ; then die "ERROR: JAVA_HOME is set to an invalid directory: $JAVA_HOME @@ -98,88 +130,120 @@ Please set the JAVA_HOME variable in your environment to match the location of your Java installation." fi else - JAVACMD="java" - which java >/dev/null 2>&1 || die "ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH. + JAVACMD=java + if ! command -v java >/dev/null 2>&1 + then + die "ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH. Please set the JAVA_HOME variable in your environment to match the location of your Java installation." + fi fi # Increase the maximum file descriptors if we can. -if [ "$cygwin" = "false" -a "$darwin" = "false" -a "$nonstop" = "false" ] ; then - MAX_FD_LIMIT=`ulimit -H -n` - if [ $? -eq 0 ] ; then - if [ "$MAX_FD" = "maximum" -o "$MAX_FD" = "max" ] ; then - MAX_FD="$MAX_FD_LIMIT" - fi - ulimit -n $MAX_FD - if [ $? -ne 0 ] ; then - warn "Could not set maximum file descriptor limit: $MAX_FD" - fi - else - warn "Could not query maximum file descriptor limit: $MAX_FD_LIMIT" - fi +if ! "$cygwin" && ! "$darwin" && ! "$nonstop" ; then + case $MAX_FD in #( + max*) + # In POSIX sh, ulimit -H is undefined. That's why the result is checked to see if it worked. + # shellcheck disable=SC2039,SC3045 + MAX_FD=$( ulimit -H -n ) || + warn "Could not query maximum file descriptor limit" + esac + case $MAX_FD in #( + '' | soft) :;; #( + *) + # In POSIX sh, ulimit -n is undefined. That's why the result is checked to see if it worked. + # shellcheck disable=SC2039,SC3045 + ulimit -n "$MAX_FD" || + warn "Could not set maximum file descriptor limit to $MAX_FD" + esac fi -# For Darwin, add options to specify how the application appears in the dock -if $darwin; then - GRADLE_OPTS="$GRADLE_OPTS \"-Xdock:name=$APP_NAME\" \"-Xdock:icon=$APP_HOME/media/gradle.icns\"" -fi +# Collect all arguments for the java command, stacking in reverse order: +# * args from the command line +# * the main class name +# * -classpath +# * -D...appname settings +# * --module-path (only if needed) +# * DEFAULT_JVM_OPTS, JAVA_OPTS, and GRADLE_OPTS environment variables. # For Cygwin or MSYS, switch paths to Windows format before running java -if [ "$cygwin" = "true" -o "$msys" = "true" ] ; then - APP_HOME=`cygpath --path --mixed "$APP_HOME"` - CLASSPATH=`cygpath --path --mixed "$CLASSPATH"` - - JAVACMD=`cygpath --unix "$JAVACMD"` - - # We build the pattern for arguments to be converted via cygpath - ROOTDIRSRAW=`find -L / -maxdepth 1 -mindepth 1 -type d 2>/dev/null` - SEP="" - for dir in $ROOTDIRSRAW ; do - ROOTDIRS="$ROOTDIRS$SEP$dir" - SEP="|" - done - OURCYGPATTERN="(^($ROOTDIRS))" - # Add a user-defined pattern to the cygpath arguments - if [ "$GRADLE_CYGPATTERN" != "" ] ; then - OURCYGPATTERN="$OURCYGPATTERN|($GRADLE_CYGPATTERN)" - fi +if "$cygwin" || "$msys" ; then + APP_HOME=$( cygpath --path --mixed "$APP_HOME" ) + CLASSPATH=$( cygpath --path --mixed "$CLASSPATH" ) + + JAVACMD=$( cygpath --unix "$JAVACMD" ) + # Now convert the arguments - kludge to limit ourselves to /bin/sh - i=0 - for arg in "$@" ; do - CHECK=`echo "$arg"|egrep -c "$OURCYGPATTERN" -` - CHECK2=`echo "$arg"|egrep -c "^-"` ### Determine if an option - - if [ $CHECK -ne 0 ] && [ $CHECK2 -eq 0 ] ; then ### Added a condition - eval `echo args$i`=`cygpath --path --ignore --mixed "$arg"` - else - eval `echo args$i`="\"$arg\"" + for arg do + if + case $arg in #( + -*) false ;; # don't mess with options #( + /?*) t=${arg#/} t=/${t%%/*} # looks like a POSIX filepath + [ -e "$t" ] ;; #( + *) false ;; + esac + then + arg=$( cygpath --path --ignore --mixed "$arg" ) fi - i=`expr $i + 1` + # Roll the args list around exactly as many times as the number of + # args, so each arg winds up back in the position where it started, but + # possibly modified. + # + # NB: a `for` loop captures its iteration list before it begins, so + # changing the positional parameters here affects neither the number of + # iterations, nor the values presented in `arg`. + shift # remove old arg + set -- "$@" "$arg" # push replacement arg done - case $i in - 0) set -- ;; - 1) set -- "$args0" ;; - 2) set -- "$args0" "$args1" ;; - 3) set -- "$args0" "$args1" "$args2" ;; - 4) set -- "$args0" "$args1" "$args2" "$args3" ;; - 5) set -- "$args0" "$args1" "$args2" "$args3" "$args4" ;; - 6) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" ;; - 7) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" ;; - 8) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" "$args7" ;; - 9) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" "$args7" "$args8" ;; - esac fi -# Escape application args -save () { - for i do printf %s\\n "$i" | sed "s/'/'\\\\''/g;1s/^/'/;\$s/\$/' \\\\/" ; done - echo " " -} -APP_ARGS=`save "$@"` -# Collect all arguments for the java command, following the shell quoting and substitution rules -eval set -- $DEFAULT_JVM_OPTS $JAVA_OPTS $GRADLE_OPTS "\"-Dorg.gradle.appname=$APP_BASE_NAME\"" -classpath "\"$CLASSPATH\"" org.gradle.wrapper.GradleWrapperMain "$APP_ARGS" +# Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script. +DEFAULT_JVM_OPTS='"-Xmx64m" "-Xms64m"' + +# Collect all arguments for the java command: +# * DEFAULT_JVM_OPTS, JAVA_OPTS, JAVA_OPTS, and optsEnvironmentVar are not allowed to contain shell fragments, +# and any embedded shellness will be escaped. +# * For example: A user cannot expect ${Hostname} to be expanded, as it is an environment variable and will be +# treated as '${Hostname}' itself on the command line. + +set -- \ + "-Dorg.gradle.appname=$APP_BASE_NAME" \ + -classpath "$CLASSPATH" \ + org.gradle.wrapper.GradleWrapperMain \ + "$@" + +# Stop when "xargs" is not available. +if ! command -v xargs >/dev/null 2>&1 +then + die "xargs is not available" +fi + +# Use "xargs" to parse quoted args. +# +# With -n1 it outputs one arg per line, with the quotes and backslashes removed. +# +# In Bash we could simply go: +# +# readarray ARGS < <( xargs -n1 <<<"$var" ) && +# set -- "${ARGS[@]}" "$@" +# +# but POSIX shell has neither arrays nor command substitution, so instead we +# post-process each arg (as a line of input to sed) to backslash-escape any +# character that might be a shell metacharacter, then use eval to reverse +# that process (while maintaining the separation between arguments), and wrap +# the whole thing up as a single "set" statement. +# +# This will of course break if any of these variables contains a newline or +# an unmatched quote. +# + +eval "set -- $( + printf '%s\n' "$DEFAULT_JVM_OPTS $JAVA_OPTS $GRADLE_OPTS" | + xargs -n1 | + sed ' s~[^-[:alnum:]+,./:=@_]~\\&~g; ' | + tr '\n' ' ' + )" '"$@"' exec "$JAVACMD" "$@" diff --git a/gradlew.bat b/gradlew.bat index 107acd32..7101f8e4 100644 --- a/gradlew.bat +++ b/gradlew.bat @@ -1,89 +1,92 @@ -@rem -@rem Copyright 2015 the original author or authors. -@rem -@rem Licensed under the Apache License, Version 2.0 (the "License"); -@rem you may not use this file except in compliance with the License. -@rem You may obtain a copy of the License at -@rem -@rem https://www.apache.org/licenses/LICENSE-2.0 -@rem -@rem Unless required by applicable law or agreed to in writing, software -@rem distributed under the License is distributed on an "AS IS" BASIS, -@rem WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -@rem See the License for the specific language governing permissions and -@rem limitations under the License. -@rem - -@if "%DEBUG%" == "" @echo off -@rem ########################################################################## -@rem -@rem Gradle startup script for Windows -@rem -@rem ########################################################################## - -@rem Set local scope for the variables with windows NT shell -if "%OS%"=="Windows_NT" setlocal - -set DIRNAME=%~dp0 -if "%DIRNAME%" == "" set DIRNAME=. -set APP_BASE_NAME=%~n0 -set APP_HOME=%DIRNAME% - -@rem Resolve any "." and ".." in APP_HOME to make it shorter. -for %%i in ("%APP_HOME%") do set APP_HOME=%%~fi - -@rem Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script. -set DEFAULT_JVM_OPTS="-Xmx64m" "-Xms64m" - -@rem Find java.exe -if defined JAVA_HOME goto findJavaFromJavaHome - -set JAVA_EXE=java.exe -%JAVA_EXE% -version >NUL 2>&1 -if "%ERRORLEVEL%" == "0" goto execute - -echo. -echo ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH. -echo. -echo Please set the JAVA_HOME variable in your environment to match the -echo location of your Java installation. - -goto fail - -:findJavaFromJavaHome -set JAVA_HOME=%JAVA_HOME:"=% -set JAVA_EXE=%JAVA_HOME%/bin/java.exe - -if exist "%JAVA_EXE%" goto execute - -echo. -echo ERROR: JAVA_HOME is set to an invalid directory: %JAVA_HOME% -echo. -echo Please set the JAVA_HOME variable in your environment to match the -echo location of your Java installation. - -goto fail - -:execute -@rem Setup the command line - -set CLASSPATH=%APP_HOME%\gradle\wrapper\gradle-wrapper.jar - - -@rem Execute Gradle -"%JAVA_EXE%" %DEFAULT_JVM_OPTS% %JAVA_OPTS% %GRADLE_OPTS% "-Dorg.gradle.appname=%APP_BASE_NAME%" -classpath "%CLASSPATH%" org.gradle.wrapper.GradleWrapperMain %* - -:end -@rem End local scope for the variables with windows NT shell -if "%ERRORLEVEL%"=="0" goto mainEnd - -:fail -rem Set variable GRADLE_EXIT_CONSOLE if you need the _script_ return code instead of -rem the _cmd.exe /c_ return code! -if not "" == "%GRADLE_EXIT_CONSOLE%" exit 1 -exit /b 1 - -:mainEnd -if "%OS%"=="Windows_NT" endlocal - -:omega +@rem +@rem Copyright 2015 the original author or authors. +@rem +@rem Licensed under the Apache License, Version 2.0 (the "License"); +@rem you may not use this file except in compliance with the License. +@rem You may obtain a copy of the License at +@rem +@rem https://www.apache.org/licenses/LICENSE-2.0 +@rem +@rem Unless required by applicable law or agreed to in writing, software +@rem distributed under the License is distributed on an "AS IS" BASIS, +@rem WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +@rem See the License for the specific language governing permissions and +@rem limitations under the License. +@rem + +@if "%DEBUG%"=="" @echo off +@rem ########################################################################## +@rem +@rem Gradle startup script for Windows +@rem +@rem ########################################################################## + +@rem Set local scope for the variables with windows NT shell +if "%OS%"=="Windows_NT" setlocal + +set DIRNAME=%~dp0 +if "%DIRNAME%"=="" set DIRNAME=. +@rem This is normally unused +set APP_BASE_NAME=%~n0 +set APP_HOME=%DIRNAME% + +@rem Resolve any "." and ".." in APP_HOME to make it shorter. +for %%i in ("%APP_HOME%") do set APP_HOME=%%~fi + +@rem Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script. +set DEFAULT_JVM_OPTS="-Xmx64m" "-Xms64m" + +@rem Find java.exe +if defined JAVA_HOME goto findJavaFromJavaHome + +set JAVA_EXE=java.exe +%JAVA_EXE% -version >NUL 2>&1 +if %ERRORLEVEL% equ 0 goto execute + +echo. 1>&2 +echo ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH. 1>&2 +echo. 1>&2 +echo Please set the JAVA_HOME variable in your environment to match the 1>&2 +echo location of your Java installation. 1>&2 + +goto fail + +:findJavaFromJavaHome +set JAVA_HOME=%JAVA_HOME:"=% +set JAVA_EXE=%JAVA_HOME%/bin/java.exe + +if exist "%JAVA_EXE%" goto execute + +echo. 1>&2 +echo ERROR: JAVA_HOME is set to an invalid directory: %JAVA_HOME% 1>&2 +echo. 1>&2 +echo Please set the JAVA_HOME variable in your environment to match the 1>&2 +echo location of your Java installation. 1>&2 + +goto fail + +:execute +@rem Setup the command line + +set CLASSPATH=%APP_HOME%\gradle\wrapper\gradle-wrapper.jar + + +@rem Execute Gradle +"%JAVA_EXE%" %DEFAULT_JVM_OPTS% %JAVA_OPTS% %GRADLE_OPTS% "-Dorg.gradle.appname=%APP_BASE_NAME%" -classpath "%CLASSPATH%" org.gradle.wrapper.GradleWrapperMain %* + +:end +@rem End local scope for the variables with windows NT shell +if %ERRORLEVEL% equ 0 goto mainEnd + +:fail +rem Set variable GRADLE_EXIT_CONSOLE if you need the _script_ return code instead of +rem the _cmd.exe /c_ return code! +set EXIT_CODE=%ERRORLEVEL% +if %EXIT_CODE% equ 0 set EXIT_CODE=1 +if not ""=="%GRADLE_EXIT_CONSOLE%" exit %EXIT_CODE% +exit /b %EXIT_CODE% + +:mainEnd +if "%OS%"=="Windows_NT" endlocal + +:omega diff --git a/ktlint.gradle b/ktlint.gradle deleted file mode 100644 index 106722a9..00000000 --- a/ktlint.gradle +++ /dev/null @@ -1,25 +0,0 @@ -configurations { - ktlint -} - -dependencies { - ktlint libs.ktlint -} - -task ktlint(type: JavaExec, group: "verification") { - description = "Check Kotlin code style." - main = "com.pinterest.ktlint.Main" - classpath = configurations.ktlint - args "-F", "src/**/*.kt", "--reporter=plain", "--reporter=checkstyle,output=${buildDir}/reports/ktlint/ktlint-checkstyle.xml" - jvmArgs("--add-opens", "java.base/java.lang=ALL-UNNAMED") -} - -check.dependsOn ktlint - -task ktlintFormat(type: JavaExec, group: "formatting") { - description = "Fix Kotlin code style deviations." - main = "com.pinterest.ktlint.Main" - classpath = configurations.ktlint - args "-F", "src/**/*.kt" - jvmArgs("--add-opens", "java.base/java.lang=ALL-UNNAMED") -} diff --git a/settings.gradle.kts b/settings.gradle.kts index 649ae7dc..90a74fe9 100644 --- a/settings.gradle.kts +++ b/settings.gradle.kts @@ -3,6 +3,7 @@ pluginManagement { gradlePluginPortal() google() mavenCentral() + maven(url = "https://plugins.gradle.org/m2/") } } dependencyResolutionManagement { diff --git a/spotless.gradle b/spotless.gradle deleted file mode 100644 index 8c3592a8..00000000 --- a/spotless.gradle +++ /dev/null @@ -1,22 +0,0 @@ -spotless { - // optional: limit format enforcement to just the files changed by this feature branch -// ratchetFrom 'origin/main' - - format 'misc', { - // define the files to apply `misc` to - target '**/*.gradle', '**/*.md', '**/.gitignore' - - // define the steps to apply to those files - indentWithSpaces() - trimTrailingWhitespace() - endWithNewline() - } - - kotlin { - target '**/*.kt' - ktlint(libs.versions.ktlint.get()) - trimTrailingWhitespace() - indentWithSpaces() - endWithNewline() - } -} \ No newline at end of file