diff --git a/app/build.gradle.kts b/app/build.gradle.kts index 896c041..d2a0e33 100644 --- a/app/build.gradle.kts +++ b/app/build.gradle.kts @@ -29,11 +29,6 @@ android { ) } } - - buildFeatures { - buildConfig = true - } - val jvm = JavaVersion.toVersion(libs.versions.jvmTarget.get()) compileOptions { sourceCompatibility = jvm @@ -42,6 +37,10 @@ android { kotlinOptions { jvmTarget = jvm.toString() } + buildFeatures { + buildConfig = true + compose = true + } } kapt { correctErrorTypes = true @@ -52,20 +51,29 @@ dependencies { implementation(libs.androidx.activity) implementation(libs.androidx.constraintlayout) + // Compose + implementation(platform(libs.compose.bom)) + implementation(libs.compose.runtime) + implementation(libs.compose.ui) + implementation(libs.compose.foundation) + implementation(libs.compose.material3) + // Navigation Compose + implementation(libs.androidx.navigation.compose) + implementation(libs.androidx.navigation.common) + kapt(libs.hilt.compiler) implementation(libs.hilt.android) implementation(libs.okhttp) implementation(libs.retrofit) - implementation(project(":core:common")) - implementation(project(":core:network")) - implementation(project(":core:database")) - implementation(project(":core:config")) - - implementation(project(":feature:splash")) - implementation(project(":feature:schedule")) - implementation(project(":feature:progress")) - implementation(project(":feature:news")) + implementation(projects.core.common) + implementation(projects.core.config) + implementation(projects.core.navigation) + implementation(projects.core.ui) + implementation(projects.feature.splash) + implementation(projects.feature.schedule) + implementation(projects.feature.progress) + implementation(projects.feature.news) } \ No newline at end of file diff --git a/app/src/main/AndroidManifest.xml b/app/src/main/AndroidManifest.xml index 3d5f9c7..6b57162 100644 --- a/app/src/main/AndroidManifest.xml +++ b/app/src/main/AndroidManifest.xml @@ -5,7 +5,7 @@ - when (result) { - is DataResult.Data -> { - val src = if (result.refreshedFromNetwork) "NETWORK" else "CACHE" - Log.d(LOG_TAG, "FROM $src: ${result.data}") - } - - is DataResult.Error -> { - Log.e(LOG_TAG, "ERROR: $result") - } - } - } + setContent { + TSUDeskApp() } } } diff --git a/app/src/main/java/ru/fincode/tsudesk/TSUDeskApp.kt b/app/src/main/java/ru/fincode/tsudesk/TSUDeskApp.kt deleted file mode 100644 index 315b238..0000000 --- a/app/src/main/java/ru/fincode/tsudesk/TSUDeskApp.kt +++ /dev/null @@ -1,19 +0,0 @@ -package ru.fincode.tsudesk - -import android.app.Application -import dagger.hilt.android.HiltAndroidApp -import kotlinx.coroutines.CoroutineScope -import kotlinx.coroutines.Dispatchers -import kotlinx.coroutines.SupervisorJob - -const val LOG_TAG = "NETWORK_DEBUG" - -@HiltAndroidApp -class TSUDeskApp : Application() { - -// private val appScope = CoroutineScope(SupervisorJob() + Dispatchers.IO) - - override fun onCreate() { - super.onCreate() - } -} diff --git a/app/src/main/java/ru/fincode/tsudesk/ui/TSUDeskApp.kt b/app/src/main/java/ru/fincode/tsudesk/ui/TSUDeskApp.kt new file mode 100644 index 0000000..c301c87 --- /dev/null +++ b/app/src/main/java/ru/fincode/tsudesk/ui/TSUDeskApp.kt @@ -0,0 +1,26 @@ +package ru.fincode.tsudesk.ui + +import androidx.compose.foundation.layout.PaddingValues +import androidx.compose.material3.MaterialTheme +import androidx.compose.material3.Surface +import androidx.compose.runtime.Composable +import androidx.compose.ui.Modifier +import androidx.navigation.compose.rememberNavController +import ru.fincode.tsudesk.ui.navigation.AppNavHost + +@Composable +fun TSUDeskApp() { + val navController = rememberNavController() + + MaterialTheme { + Surface( + modifier = Modifier, + color = MaterialTheme.colorScheme.background + ) { + AppNavHost( + navController = navController, + contentPadding = PaddingValues() + ) + } + } +} diff --git a/app/src/main/java/ru/fincode/tsudesk/ui/navigation/AppNavHost.kt b/app/src/main/java/ru/fincode/tsudesk/ui/navigation/AppNavHost.kt new file mode 100644 index 0000000..2ee8cf3 --- /dev/null +++ b/app/src/main/java/ru/fincode/tsudesk/ui/navigation/AppNavHost.kt @@ -0,0 +1,31 @@ +package ru.fincode.tsudesk.ui.navigation + +import androidx.compose.foundation.layout.PaddingValues +import androidx.compose.runtime.Composable +import androidx.navigation.NavHostController +import androidx.navigation.compose.NavHost +import androidx.navigation.compose.navigation +import ru.fincode.tsudesk.core.navigation.AppRoute +import ru.fincode.tsudesk.feature.schedule.ui.navigation.scheduleGraph +import ru.fincode.tsudesk.feature.splash.ui.navigation.splashGraph + +@Composable +fun AppNavHost( + navController: NavHostController, + contentPadding: PaddingValues +) { + NavHost( + navController = navController, + startDestination = AppRoute.Splash + ) { + splashGraph(navController) + + navigation( + startDestination = AppRoute.Schedule + ) { + scheduleGraph(navController) +// newsGraph(navController) +// progressGraph(navController) + } + } +} diff --git a/build.gradle.kts b/build.gradle.kts index 152f7ec..35e812c 100644 --- a/build.gradle.kts +++ b/build.gradle.kts @@ -1,3 +1,6 @@ +import com.android.build.api.dsl.ApplicationExtension +import com.android.build.api.dsl.LibraryExtension + plugins { alias(libs.plugins.hilt) apply false alias(libs.plugins.kotlin.kapt) apply false @@ -5,4 +8,22 @@ plugins { alias(libs.plugins.kotlin.android) apply false alias(libs.plugins.android.application) apply false alias(libs.plugins.android.library) apply false -} \ No newline at end of file +} + +subprojects { + plugins.withId("com.android.application") { + extensions.configure { + composeOptions { + kotlinCompilerExtensionVersion = libs.versions.kotlinCompilerExtension.get() + } + } + } + + plugins.withId("com.android.library") { + extensions.configure { + composeOptions { + kotlinCompilerExtensionVersion = libs.versions.kotlinCompilerExtension.get() + } + } + } +} diff --git a/core/common/build.gradle.kts b/core/common/build.gradle.kts index 8615813..365aa0f 100644 --- a/core/common/build.gradle.kts +++ b/core/common/build.gradle.kts @@ -29,6 +29,9 @@ android { kotlinOptions { jvmTarget = jvm.toString() } + buildFeatures { + buildConfig = true + } } dependencies { diff --git a/core/config/build.gradle.kts b/core/config/build.gradle.kts index 9618eb3..832d6a8 100644 --- a/core/config/build.gradle.kts +++ b/core/config/build.gradle.kts @@ -22,6 +22,9 @@ android { kotlinOptions { jvmTarget = jvm.toString() } + buildFeatures { + buildConfig = true + } } kapt { correctErrorTypes = true @@ -30,9 +33,8 @@ dependencies { kapt(libs.hilt.compiler) implementation(libs.hilt.android) - // Kotlin Serialization implementation(libs.kotlinx.serialization.json) - implementation(project(":core:network")) - implementation(project(":core:common")) + implementation(projects.core.network) + implementation(projects.core.common) } \ No newline at end of file diff --git a/core/database/build.gradle.kts b/core/database/build.gradle.kts index 5ce2e25..31de609 100644 --- a/core/database/build.gradle.kts +++ b/core/database/build.gradle.kts @@ -29,6 +29,9 @@ android { kotlinOptions { jvmTarget = jvm.toString() } + buildFeatures { + buildConfig = true + } } kapt { correctErrorTypes = true diff --git a/core/navigation/build.gradle.kts b/core/navigation/build.gradle.kts new file mode 100644 index 0000000..acdd578 --- /dev/null +++ b/core/navigation/build.gradle.kts @@ -0,0 +1,47 @@ +plugins { + alias(libs.plugins.android.library) + alias(libs.plugins.kotlin.android) + alias(libs.plugins.kotlin.serialization) +} + +android { + namespace = "ru.fincode.tsudesk.core.navigation" + compileSdk = libs.versions.compileSdk.get().toInt() + defaultConfig { + minSdk = libs.versions.minSdk.get().toInt() + consumerProguardFiles("consumer-rules.pro") + } + + buildTypes { + release { + isMinifyEnabled = false + proguardFiles( + getDefaultProguardFile("proguard-android-optimize.txt"), "proguard-rules.pro" + ) + } + } + + val jvm = JavaVersion.toVersion(libs.versions.jvmTarget.get()) + compileOptions { + sourceCompatibility = jvm + targetCompatibility = jvm + } + kotlinOptions { + jvmTarget = jvm.toString() + } + buildFeatures { + buildConfig = true + compose = true + } +} +dependencies { + implementation(libs.kotlinx.serialization.json) + // Compose + implementation(platform(libs.compose.bom)) + implementation(libs.compose.runtime) + // Navigation Compose + implementation(libs.androidx.navigation.compose) + implementation(libs.androidx.navigation.common) + + implementation(projects.core.ui) +} \ No newline at end of file diff --git a/core/navigation/consumer-rules.pro b/core/navigation/consumer-rules.pro new file mode 100644 index 0000000..e69de29 diff --git a/core/navigation/proguard-rules.pro b/core/navigation/proguard-rules.pro new file mode 100644 index 0000000..481bb43 --- /dev/null +++ b/core/navigation/proguard-rules.pro @@ -0,0 +1,21 @@ +# Add project specific ProGuard rules here. +# You can control the set of applied configuration files using the +# proguardFiles setting in build.gradle. +# +# For more details, see +# http://developer.android.com/guide/developing/tools/proguard.html + +# If your project uses WebView with JS, uncomment the following +# and specify the fully qualified class name to the JavaScript interface +# class: +#-keepclassmembers class fqcn.of.javascript.interface.for.webview { +# public *; +#} + +# Uncomment this to preserve the line number information for +# debugging stack traces. +#-keepattributes SourceFile,LineNumberTable + +# If you keep the line number information, uncomment this to +# hide the original source file name. +#-renamesourcefileattribute SourceFile \ No newline at end of file diff --git a/core/navigation/src/main/java/ru/fincode/tsudesk/core/navigation/AppRoute.kt b/core/navigation/src/main/java/ru/fincode/tsudesk/core/navigation/AppRoute.kt new file mode 100644 index 0000000..d7a3c50 --- /dev/null +++ b/core/navigation/src/main/java/ru/fincode/tsudesk/core/navigation/AppRoute.kt @@ -0,0 +1,37 @@ +package ru.fincode.tsudesk.core.navigation + +import kotlinx.serialization.Serializable + +@Serializable +sealed interface AppRoute { + + @Serializable + data object Splash : AppRoute + + /** + * Root-граф приложения после сплеша. + * Внутри него лежат табы: Schedule/News/Progress. + */ + @Serializable + data object Main : AppRoute + + // Tabs + @Serializable + data object Schedule : AppRoute + + @Serializable + data object News : AppRoute + + @Serializable + data object Progress : AppRoute + + @Serializable + data class ScheduleDetails( + val lessonId: Long + ) : AppRoute + + @Serializable + data class NewsDetails( + val id: String + ) : AppRoute +} diff --git a/core/navigation/src/main/java/ru/fincode/tsudesk/core/navigation/NavBackStackEntryExt.kt b/core/navigation/src/main/java/ru/fincode/tsudesk/core/navigation/NavBackStackEntryExt.kt new file mode 100644 index 0000000..b882eab --- /dev/null +++ b/core/navigation/src/main/java/ru/fincode/tsudesk/core/navigation/NavBackStackEntryExt.kt @@ -0,0 +1,6 @@ +package ru.fincode.tsudesk.core.navigation + +import androidx.navigation.NavBackStackEntry +import androidx.navigation.toRoute + +inline fun NavBackStackEntry.route(): T = toRoute() diff --git a/core/navigation/src/main/java/ru/fincode/tsudesk/core/navigation/NavControllerExt.kt b/core/navigation/src/main/java/ru/fincode/tsudesk/core/navigation/NavControllerExt.kt new file mode 100644 index 0000000..20116cc --- /dev/null +++ b/core/navigation/src/main/java/ru/fincode/tsudesk/core/navigation/NavControllerExt.kt @@ -0,0 +1,28 @@ +package ru.fincode.tsudesk.core.navigation + +import androidx.navigation.NavController +import androidx.navigation.NavGraph.Companion.findStartDestination +import androidx.navigation.NavOptionsBuilder + + +fun NavController.navigateToTopLevel(destination: TopLevelDestination) { + val route = destination.toRoute() + navigate(route) { + popUpTo(graph.findStartDestination().id) { + saveState = true + } + launchSingleTop = true + restoreState = true + } +} + +fun NavController.navigateRoute( + route: AppRoute, + builder: (NavOptionsBuilder.() -> Unit)? = null +) { + if (builder == null) { + navigate(route) + } else { + navigate(route, builder) + } +} diff --git a/core/navigation/src/main/java/ru/fincode/tsudesk/core/navigation/TopLevelDestination.kt b/core/navigation/src/main/java/ru/fincode/tsudesk/core/navigation/TopLevelDestination.kt new file mode 100644 index 0000000..1645ac4 --- /dev/null +++ b/core/navigation/src/main/java/ru/fincode/tsudesk/core/navigation/TopLevelDestination.kt @@ -0,0 +1,22 @@ +package ru.fincode.tsudesk.core.navigation + +import kotlinx.serialization.Serializable + +@Serializable +enum class TopLevelDestination { + SCHEDULE, + NEWS, + PROGRESS +} + +fun TopLevelDestination.toRoute(): AppRoute = when (this) { + TopLevelDestination.SCHEDULE -> AppRoute.Schedule + TopLevelDestination.NEWS -> AppRoute.News + TopLevelDestination.PROGRESS -> AppRoute.Progress +} + +val TOP_LEVEL_DESTINATIONS: List = listOf( + TopLevelDestination.SCHEDULE, + TopLevelDestination.NEWS, + TopLevelDestination.PROGRESS +) diff --git a/core/network/build.gradle.kts b/core/network/build.gradle.kts index 3559670..30bed52 100644 --- a/core/network/build.gradle.kts +++ b/core/network/build.gradle.kts @@ -13,9 +13,6 @@ android { minSdk = libs.versions.minSdk.get().toInt() consumerProguardFiles("consumer-rules.pro") } - buildFeatures { - buildConfig = true - } buildTypes { release { isMinifyEnabled = false @@ -33,6 +30,9 @@ android { kotlinOptions { jvmTarget = jvm.toString() } + buildFeatures { + buildConfig = true + } } kapt { correctErrorTypes = true @@ -51,5 +51,5 @@ dependencies { api(libs.moshiKotlin) api(libs.retrofitMoshi) - implementation(project(":core:common")) + implementation(projects.core.common) } \ No newline at end of file diff --git a/core/network/src/main/java/ru/fincode/tsudesk/core/network/interceptor/DebugInterceptor.kt b/core/network/src/main/java/ru/fincode/tsudesk/core/network/interceptor/DebugInterceptor.kt index edf203e..679a70b 100644 --- a/core/network/src/main/java/ru/fincode/tsudesk/core/network/interceptor/DebugInterceptor.kt +++ b/core/network/src/main/java/ru/fincode/tsudesk/core/network/interceptor/DebugInterceptor.kt @@ -6,7 +6,7 @@ import okhttp3.Response import javax.inject.Inject import javax.inject.Singleton -private const val TAG = "NETWORK_DEBUG" +private const val LOG_DEBUG_TAG = "LOG_DEBUG_TAG" @Singleton class DebugInterceptor @Inject constructor() : Interceptor { @@ -14,8 +14,8 @@ class DebugInterceptor @Inject constructor() : Interceptor { override fun intercept(chain: Interceptor.Chain): Response { val request = chain.request() - Log.d(TAG, "URL: ${request.url}") - Log.d(TAG, "Method: ${request.method}") + Log.d(LOG_DEBUG_TAG, "URL: ${request.url}") + Log.d(LOG_DEBUG_TAG, "Method: ${request.method}") return chain.proceed(request) } diff --git a/core/network/src/main/java/ru/fincode/tsudesk/core/network/interceptor/NetEventLogger.kt b/core/network/src/main/java/ru/fincode/tsudesk/core/network/interceptor/NetEventLogger.kt index ca2b03a..0c5e8f1 100644 --- a/core/network/src/main/java/ru/fincode/tsudesk/core/network/interceptor/NetEventLogger.kt +++ b/core/network/src/main/java/ru/fincode/tsudesk/core/network/interceptor/NetEventLogger.kt @@ -6,15 +6,15 @@ import okhttp3.EventListener import java.io.IOException import java.net.InetAddress -private const val LOG_TAG = "NETWORK_DEBUG" +private const val LOG_DEBUG_TAG = "LOG_DEBUG_TAG" class NetEventLogger : EventListener() { override fun dnsStart(call: Call, domainName: String) { - Log.d(LOG_TAG, "dnsStart: $domainName") + Log.d(LOG_DEBUG_TAG, "dnsStart: $domainName") } override fun dnsEnd(call: Call, domainName: String, inetAddressList: List) { - Log.d(LOG_TAG, "dnsEnd: $domainName -> $inetAddressList") + Log.d(LOG_DEBUG_TAG, "dnsEnd: $domainName -> $inetAddressList") } override fun connectStart( @@ -22,30 +22,30 @@ class NetEventLogger : EventListener() { inetSocketAddress: java.net.InetSocketAddress, proxy: java.net.Proxy ) { - Log.d(LOG_TAG, "connectStart: $inetSocketAddress proxy=$proxy") + Log.d(LOG_DEBUG_TAG, "connectStart: $inetSocketAddress proxy=$proxy") } override fun secureConnectStart(call: Call) { - Log.d(LOG_TAG, "tlsStart") + Log.d(LOG_DEBUG_TAG, "tlsStart") } override fun secureConnectEnd(call: Call, handshake: okhttp3.Handshake?) { - Log.d(LOG_TAG, "tlsEnd: $handshake") + Log.d(LOG_DEBUG_TAG, "tlsEnd: $handshake") } override fun requestHeadersStart(call: Call) { - Log.d(LOG_TAG, "reqHeadersStart") + Log.d(LOG_DEBUG_TAG, "reqHeadersStart") } override fun responseHeadersStart(call: Call) { - Log.d(LOG_TAG, "respHeadersStart") + Log.d(LOG_DEBUG_TAG, "respHeadersStart") } override fun callFailed(call: Call, ioe: IOException) { - Log.e(LOG_TAG, "callFailed", ioe) + Log.e(LOG_DEBUG_TAG, "callFailed", ioe) } override fun callEnd(call: Call) { - Log.d(LOG_TAG, "callEnd") + Log.d(LOG_DEBUG_TAG, "callEnd") } } diff --git a/core/ui/build.gradle.kts b/core/ui/build.gradle.kts index ab480b6..b0f0c25 100644 --- a/core/ui/build.gradle.kts +++ b/core/ui/build.gradle.kts @@ -30,6 +30,9 @@ android { kotlinOptions { jvmTarget = jvm.toString() } + buildFeatures { + buildConfig = true + } } dependencies { implementation(libs.core.ktx) diff --git a/feature/news/build.gradle.kts b/feature/news/build.gradle.kts index 20dfbeb..cc34dbe 100644 --- a/feature/news/build.gradle.kts +++ b/feature/news/build.gradle.kts @@ -31,7 +31,7 @@ android { } dependencies { - implementation(libs.core.ktx) implementation(libs.androidx.appcompat) implementation(libs.material) + implementation(libs.core.ktx) } \ No newline at end of file diff --git a/feature/news/src/main/AndroidManifest.xml b/feature/news/src/main/AndroidManifest.xml deleted file mode 100644 index a5918e6..0000000 --- a/feature/news/src/main/AndroidManifest.xml +++ /dev/null @@ -1,4 +0,0 @@ - - - - \ No newline at end of file diff --git a/feature/progress/src/main/AndroidManifest.xml b/feature/progress/src/main/AndroidManifest.xml deleted file mode 100644 index a5918e6..0000000 --- a/feature/progress/src/main/AndroidManifest.xml +++ /dev/null @@ -1,4 +0,0 @@ - - - - \ No newline at end of file diff --git a/feature/schedule/build.gradle.kts b/feature/schedule/build.gradle.kts index 4a21b08..8635a70 100644 --- a/feature/schedule/build.gradle.kts +++ b/feature/schedule/build.gradle.kts @@ -32,6 +32,10 @@ android { kotlinOptions { jvmTarget = jvm.toString() } + buildFeatures { + buildConfig = true + compose = true + } } kapt { correctErrorTypes = true @@ -40,10 +44,25 @@ dependencies { implementation(libs.androidx.appcompat) implementation(libs.material) + // Compose + implementation(platform(libs.compose.bom)) + implementation(libs.compose.runtime) + implementation(libs.compose.ui) + implementation(libs.compose.foundation) + implementation(libs.compose.material3) + + // Navigation Compose + implementation(libs.androidx.navigation.compose) + implementation(libs.androidx.navigation.common) + kapt(libs.hilt.compiler) implementation(libs.hilt.android) + implementation(libs.hilt.navigation.compose) - implementation(project(":core:network")) - implementation(project(":core:database")) - implementation(project(":core:common")) + implementation(projects.core.network) + implementation(projects.core.database) + implementation(projects.core.common) + implementation(projects.core.config) + implementation(projects.core.ui) + implementation(projects.core.navigation) } \ No newline at end of file diff --git a/feature/schedule/src/main/AndroidManifest.xml b/feature/schedule/src/main/AndroidManifest.xml deleted file mode 100644 index a5918e6..0000000 --- a/feature/schedule/src/main/AndroidManifest.xml +++ /dev/null @@ -1,4 +0,0 @@ - - - - \ No newline at end of file diff --git a/feature/schedule/src/main/java/ru/fincode/tsudesk/feature/schedule/presentation/ui/ScheduleRoute.kt b/feature/schedule/src/main/java/ru/fincode/tsudesk/feature/schedule/presentation/ui/ScheduleRoute.kt new file mode 100644 index 0000000..8ebd106 --- /dev/null +++ b/feature/schedule/src/main/java/ru/fincode/tsudesk/feature/schedule/presentation/ui/ScheduleRoute.kt @@ -0,0 +1,22 @@ +package ru.fincode.tsudesk.feature.schedule.presentation.ui + +import androidx.compose.foundation.layout.Box +import androidx.compose.foundation.layout.fillMaxSize +import androidx.compose.material3.Text +import androidx.compose.runtime.Composable +import androidx.compose.ui.Alignment +import androidx.compose.ui.Modifier +import androidx.compose.ui.graphics.Color + +@Composable +fun ScheduleScreen() { + Box( + modifier = Modifier.fillMaxSize(), + contentAlignment = Alignment.Center + ) { + Text( + text = "Schedule", + color = Color.Black + ) + } +} diff --git a/feature/schedule/src/main/java/ru/fincode/tsudesk/feature/schedule/presentation/ui/navigation/ScheduleGraph.kt b/feature/schedule/src/main/java/ru/fincode/tsudesk/feature/schedule/presentation/ui/navigation/ScheduleGraph.kt new file mode 100644 index 0000000..b35bf98 --- /dev/null +++ b/feature/schedule/src/main/java/ru/fincode/tsudesk/feature/schedule/presentation/ui/navigation/ScheduleGraph.kt @@ -0,0 +1,21 @@ +package ru.fincode.tsudesk.feature.schedule.ui.navigation + +import androidx.navigation.NavGraphBuilder +import androidx.navigation.NavHostController +import androidx.navigation.compose.composable +import ru.fincode.tsudesk.core.navigation.AppRoute +import ru.fincode.tsudesk.feature.schedule.presentation.ui.ScheduleScreen + +fun NavGraphBuilder.scheduleGraph( + navController: NavHostController +) { + composable { + ScheduleScreen() + } + + // регистрация экрана детальной информации о занятии + // composable { backStackEntry -> + // // val args = backStackEntry.toRoute() + // // ScheduleDetailsRoute(lessonId = args.lessonId) + // } +} diff --git a/feature/splash/build.gradle.kts b/feature/splash/build.gradle.kts index 6d6c69d..72b8c56 100644 --- a/feature/splash/build.gradle.kts +++ b/feature/splash/build.gradle.kts @@ -8,10 +8,6 @@ plugins { android { namespace = "ru.fincode.tsudesk.feature.splash" - buildFeatures { compose = true } - composeOptions { - kotlinCompilerExtensionVersion = libs.versions.kotlinCompilerExtension.get() - } compileSdk = libs.versions.compileSdk.get().toInt() defaultConfig { minSdk = libs.versions.minSdk.get().toInt() @@ -35,6 +31,10 @@ android { kotlinOptions { jvmTarget = jvm.toString() } + buildFeatures { + buildConfig = true + compose = true + } } kapt { correctErrorTypes = true @@ -43,17 +43,24 @@ dependencies { implementation(libs.androidx.appcompat) implementation(libs.material) + // Compose implementation(platform(libs.compose.bom)) + implementation(libs.compose.runtime) implementation(libs.compose.ui) implementation(libs.compose.foundation) implementation(libs.compose.material3) + // Navigation Compose + implementation(libs.androidx.navigation.compose) + implementation(libs.androidx.navigation.common) + kapt(libs.hilt.compiler) implementation(libs.hilt.android) implementation(libs.hilt.navigation.compose) - implementation(project(":core:network")) - implementation(project(":core:common")) - implementation(project(":core:config")) - implementation(project(":core:ui")) + implementation(projects.core.network) + implementation(projects.core.common) + implementation(projects.core.config) + implementation(projects.core.ui) + implementation(projects.core.navigation) } \ No newline at end of file diff --git a/feature/splash/src/androidTest/java/ru/fincode/tsudesk/feature/splash/ExampleInstrumentedTest.kt b/feature/splash/src/androidTest/java/ru/fincode/tsudesk/feature/splash/ExampleInstrumentedTest.kt deleted file mode 100644 index fe0b316..0000000 --- a/feature/splash/src/androidTest/java/ru/fincode/tsudesk/feature/splash/ExampleInstrumentedTest.kt +++ /dev/null @@ -1,24 +0,0 @@ -package ru.fincode.tsudesk.feature.splash - -import androidx.test.platform.app.InstrumentationRegistry -import androidx.test.ext.junit.runners.AndroidJUnit4 - -import org.junit.Test -import org.junit.runner.RunWith - -import org.junit.Assert.* - -/** - * Instrumented test, which will execute on an Android device. - * - * See [testing documentation](http://d.android.com/tools/testing). - */ -@RunWith(AndroidJUnit4::class) -class ExampleInstrumentedTest { - @Test - fun useAppContext() { - // Context of the app under test. - val appContext = InstrumentationRegistry.getInstrumentation().targetContext - assertEquals("ru.fincode.tsudesk.feature.splash.test", appContext.packageName) - } -} \ No newline at end of file diff --git a/feature/splash/src/main/AndroidManifest.xml b/feature/splash/src/main/AndroidManifest.xml deleted file mode 100644 index a5918e6..0000000 --- a/feature/splash/src/main/AndroidManifest.xml +++ /dev/null @@ -1,4 +0,0 @@ - - - - \ No newline at end of file diff --git a/feature/splash/src/main/java/ru/fincode/tsudesk/feature/splash/ui/SplashRoute.kt b/feature/splash/src/main/java/ru/fincode/tsudesk/feature/splash/ui/SplashRoute.kt index 9dc475d..7263940 100644 --- a/feature/splash/src/main/java/ru/fincode/tsudesk/feature/splash/ui/SplashRoute.kt +++ b/feature/splash/src/main/java/ru/fincode/tsudesk/feature/splash/ui/SplashRoute.kt @@ -7,15 +7,18 @@ import androidx.lifecycle.compose.collectAsStateWithLifecycle @Composable fun SplashRoute( - onOpenMain: () -> Unit, vm: SplashViewModel = hiltViewModel() + onFinish: () -> Unit, + viewModel: SplashViewModel = hiltViewModel() ) { - val state = vm.state.collectAsStateWithLifecycle().value - SplashScreen(state) - LaunchedEffect(vm) { - vm.effects.collect { effect -> + val state = viewModel.state.collectAsStateWithLifecycle().value + + LaunchedEffect(Unit) { + viewModel.effects.collect { effect -> when (effect) { - SplashEffect.OpenMain -> onOpenMain() + SplashEffect.OpenMain -> onFinish() } } } + + SplashScreen(state = state) } diff --git a/feature/splash/src/main/java/ru/fincode/tsudesk/feature/splash/ui/SplashScreen.kt b/feature/splash/src/main/java/ru/fincode/tsudesk/feature/splash/ui/SplashScreen.kt index 65a6a36..b3ea9cc 100644 --- a/feature/splash/src/main/java/ru/fincode/tsudesk/feature/splash/ui/SplashScreen.kt +++ b/feature/splash/src/main/java/ru/fincode/tsudesk/feature/splash/ui/SplashScreen.kt @@ -1,27 +1,24 @@ package ru.fincode.tsudesk.feature.splash.ui -import androidx.compose.foundation.background -import androidx.compose.foundation.layout.* -import androidx.compose.material3.CircularProgressIndicator +import androidx.compose.foundation.layout.Box +import androidx.compose.foundation.layout.fillMaxSize +import androidx.compose.material3.Text import androidx.compose.runtime.Composable import androidx.compose.ui.Alignment import androidx.compose.ui.Modifier import androidx.compose.ui.graphics.Color -import androidx.compose.ui.unit.dp @Composable -fun SplashScreen(state: SplashUiState) { +fun SplashScreen( + state: SplashUiState +) { Box( - modifier = Modifier - .fillMaxSize() - .background(Color.Black), + modifier = Modifier.fillMaxSize(), contentAlignment = Alignment.Center ) { - Column(horizontalAlignment = Alignment.CenterHorizontally) { - if (state.isLoading) { - Spacer(Modifier.height(16.dp)) - CircularProgressIndicator() - } - } + Text( + text = state.title, + color = Color.Black + ) } } diff --git a/feature/splash/src/main/java/ru/fincode/tsudesk/feature/splash/ui/SplashUiState.kt b/feature/splash/src/main/java/ru/fincode/tsudesk/feature/splash/ui/SplashUiState.kt index 0f9fa97..642a12b 100644 --- a/feature/splash/src/main/java/ru/fincode/tsudesk/feature/splash/ui/SplashUiState.kt +++ b/feature/splash/src/main/java/ru/fincode/tsudesk/feature/splash/ui/SplashUiState.kt @@ -1,6 +1,7 @@ package ru.fincode.tsudesk.feature.splash.ui data class SplashUiState( + val title: String = "TSUDesk", val isLoading: Boolean = true, val errorMessage: String? = null ) diff --git a/feature/splash/src/main/java/ru/fincode/tsudesk/feature/splash/ui/navigation/SplashGraph.kt b/feature/splash/src/main/java/ru/fincode/tsudesk/feature/splash/ui/navigation/SplashGraph.kt new file mode 100644 index 0000000..55cba5f --- /dev/null +++ b/feature/splash/src/main/java/ru/fincode/tsudesk/feature/splash/ui/navigation/SplashGraph.kt @@ -0,0 +1,22 @@ +package ru.fincode.tsudesk.feature.splash.ui.navigation + +import androidx.navigation.NavGraphBuilder +import androidx.navigation.NavHostController +import androidx.navigation.compose.composable +import ru.fincode.tsudesk.core.navigation.AppRoute +import ru.fincode.tsudesk.feature.splash.ui.SplashRoute + +fun NavGraphBuilder.splashGraph( + navController: NavHostController +) { + composable { + SplashRoute( + onFinish = { + navController.navigate(AppRoute.Main) { + popUpTo(AppRoute.Splash) { inclusive = true } + launchSingleTop = true + } + } + ) + } +} diff --git a/feature/splash/src/test/java/ru/fincode/tsudesk/feature/splash/ExampleUnitTest.kt b/feature/splash/src/test/java/ru/fincode/tsudesk/feature/splash/ExampleUnitTest.kt deleted file mode 100644 index d1b17c4..0000000 --- a/feature/splash/src/test/java/ru/fincode/tsudesk/feature/splash/ExampleUnitTest.kt +++ /dev/null @@ -1,17 +0,0 @@ -package ru.fincode.tsudesk.feature.splash - -import org.junit.Test - -import org.junit.Assert.* - -/** - * Example local unit test, which will execute on the development machine (host). - * - * See [testing documentation](http://d.android.com/tools/testing). - */ -class ExampleUnitTest { - @Test - fun addition_isCorrect() { - assertEquals(4, 2 + 2) - } -} \ No newline at end of file diff --git a/gradle/libs.versions.toml b/gradle/libs.versions.toml index 007a51b..3f67405 100644 --- a/gradle/libs.versions.toml +++ b/gradle/libs.versions.toml @@ -18,6 +18,7 @@ activity = "1.8.0" constraintlayout = "2.1.4" compose-bom = "2024.10.00" hilt-nav-compose = "1.2.0" +navigation = "2.8.5" hilt = "2.50" retrofit = "2.11.0" @@ -28,9 +29,6 @@ lifecycle = "2.7.0" coroutines = "1.8.1" room = "2.6.1" -junit = "4.13.2" -junitVersion = "1.1.5" -espressoCore = "3.5.1" [libraries] # Android @@ -42,12 +40,15 @@ kotlinx-serialization-json = { group = "org.jetbrains.kotlinx", name = "kotlinx- material = { group = "com.google.android.material", name = "material", version.ref = "material" } androidx-activity = { group = "androidx.activity", name = "activity", version.ref = "activity" } androidx-constraintlayout = { group = "androidx.constraintlayout", name = "constraintlayout", version.ref = "constraintlayout" } -compose-bom = { group = "androidx.compose", name = "compose-bom", version.ref = "compose-bom" } -hilt-navigation-compose = { group = "androidx.hilt", name = "hilt-navigation-compose", version.ref = "hilt-nav-compose" } # Compose UI compose-ui = { group = "androidx.compose.ui", name = "ui" } compose-foundation = { group = "androidx.compose.foundation", name = "foundation" } compose-material3 = { group = "androidx.compose.material3", name = "material3" } +hilt-navigation-compose = { group = "androidx.hilt", name = "hilt-navigation-compose", version.ref = "hilt-nav-compose" } +androidx-navigation-compose = { group = "androidx.navigation", name = "navigation-compose", version.ref = "navigation" } +androidx-navigation-common = { group = "androidx.navigation", name = "navigation-common-ktx", version.ref = "navigation" } +compose-runtime = { group = "androidx.compose.runtime", name = "runtime" } +compose-bom = { group = "androidx.compose", name = "compose-bom", version.ref = "compose-bom" } # Network: okhhtp3+retrofit2 okhttp = { module = "com.squareup.okhttp3:okhttp", version.ref = "okhttp" } okhttp-logging = { module = "com.squareup.okhttp3:logging-interceptor", version.ref = "okhttp" } @@ -65,9 +66,6 @@ core-ktx = { group = "androidx.core", name = "core-ktx", version.ref = "coreKtx" room-runtime = { group = "androidx.room", name = "room-runtime", version.ref = "room" } room-ktx = { group = "androidx.room", name = "room-ktx", version.ref = "room" } room-compiler = { group = "androidx.room", name = "room-compiler", version.ref = "room" } -junit = { group = "junit", name = "junit", version.ref = "junit" } -androidx-junit = { group = "androidx.test.ext", name = "junit", version.ref = "junitVersion" } -androidx-espresso-core = { group = "androidx.test.espresso", name = "espresso-core", version.ref = "espressoCore" } [plugins] hilt = { id = "com.google.dagger.hilt.android", version.ref = "hilt" } diff --git a/settings.gradle.kts b/settings.gradle.kts index e2597a0..8f999dc 100644 --- a/settings.gradle.kts +++ b/settings.gradle.kts @@ -18,13 +18,14 @@ dependencyResolutionManagement { mavenCentral() } } - +enableFeaturePreview("TYPESAFE_PROJECT_ACCESSORS") rootProject.name = "TSUDesk" include(":app") include(":core:common") include(":core:ui") +include(":core:navigation") include(":core:network") include(":core:database") include(":core:config")