diff --git a/app/build.gradle.kts b/app/build.gradle.kts new file mode 100644 index 0000000..201015e --- /dev/null +++ b/app/build.gradle.kts @@ -0,0 +1,93 @@ +plugins { + alias(libs.plugins.android.application) + alias(libs.plugins.jetbrains.kotlin.android) + alias(libs.plugins.hilt) + alias(libs.plugins.ksp) +} + +android { + namespace = "com.planify.mobile" + compileSdk = 34 + + defaultConfig { + applicationId = "com.planify.mobile" + minSdk = 26 + targetSdk = 34 + versionCode = 1 + versionName = "0.1.0" + testInstrumentationRunner = "androidx.test.runner.AndroidJUnitRunner" + } + + buildTypes { + release { + isMinifyEnabled = true + proguardFiles(getDefaultProguardFile("proguard-android-optimize.txt"), "proguard-rules.pro") + } + } + + compileOptions { + sourceCompatibility = JavaVersion.VERSION_17 + targetCompatibility = JavaVersion.VERSION_17 + } + + kotlinOptions { + jvmTarget = "17" + } + + buildFeatures { + compose = true + } + + composeOptions { + kotlinCompilerExtensionVersion = "1.5.14" + } +} + +dependencies { + implementation(libs.androidx.core.ktx) + implementation(libs.androidx.lifecycle.runtime.ktx) + implementation(libs.androidx.lifecycle.viewmodel.compose) + implementation(libs.androidx.activity.compose) + implementation(platform(libs.androidx.compose.bom)) + implementation(libs.androidx.ui) + implementation(libs.androidx.ui.graphics) + implementation(libs.androidx.ui.tooling.preview) + implementation(libs.androidx.material3) + implementation(libs.androidx.material.icons.extended) + implementation(libs.androidx.navigation.compose) + + // Hilt + implementation(libs.hilt.android) + ksp(libs.hilt.compiler) + implementation(libs.hilt.navigation.compose) + implementation(libs.hilt.work) + ksp(libs.hilt.work.compiler) + + // Room + implementation(libs.room.runtime) + implementation(libs.room.ktx) + ksp(libs.room.compiler) + + // Coroutines + implementation(libs.kotlinx.coroutines.android) + + // Network + implementation(libs.okhttp) + implementation(libs.okhttp.logging) + + // Storage + implementation(libs.datastore.preferences) + implementation(libs.security.crypto) + + // WorkManager + implementation(libs.work.runtime.ktx) + + // Tests + testImplementation(libs.junit) + androidTestImplementation(libs.androidx.junit) + androidTestImplementation(libs.androidx.espresso.core) + androidTestImplementation(platform(libs.androidx.compose.bom)) + androidTestImplementation(libs.androidx.ui.test.junit4) + debugImplementation(libs.androidx.ui.tooling) + debugImplementation(libs.androidx.ui.test.manifest) +} diff --git a/app/src/main/AndroidManifest.xml b/app/src/main/AndroidManifest.xml new file mode 100644 index 0000000..8c6cf7a --- /dev/null +++ b/app/src/main/AndroidManifest.xml @@ -0,0 +1,31 @@ + + + + + + + + + + + + + + + + + + + + + diff --git a/app/src/main/java/com/planify/mobile/PlanifyApp.kt b/app/src/main/java/com/planify/mobile/PlanifyApp.kt new file mode 100644 index 0000000..f087ff7 --- /dev/null +++ b/app/src/main/java/com/planify/mobile/PlanifyApp.kt @@ -0,0 +1,19 @@ +package com.planify.mobile + +import android.app.Application +import androidx.hilt.work.HiltWorkerFactory +import androidx.work.Configuration +import dagger.hilt.android.HiltAndroidApp +import javax.inject.Inject + +@HiltAndroidApp +class PlanifyApp : Application(), Configuration.Provider { + + @Inject + lateinit var workerFactory: HiltWorkerFactory + + override val workManagerConfiguration: Configuration + get() = Configuration.Builder() + .setWorkerFactory(workerFactory) + .build() +} diff --git a/app/src/main/java/com/planify/mobile/di/AppModule.kt b/app/src/main/java/com/planify/mobile/di/AppModule.kt new file mode 100644 index 0000000..f42ae78 --- /dev/null +++ b/app/src/main/java/com/planify/mobile/di/AppModule.kt @@ -0,0 +1,10 @@ +package com.planify.mobile.di + +import dagger.Module +import dagger.hilt.InstallIn +import dagger.hilt.components.SingletonComponent + +@Module +@InstallIn(SingletonComponent::class) +object AppModule +// TODO #5 : fournir AppDatabase, repositories, et client CalDAV diff --git a/app/src/main/java/com/planify/mobile/ui/MainActivity.kt b/app/src/main/java/com/planify/mobile/ui/MainActivity.kt new file mode 100644 index 0000000..f866341 --- /dev/null +++ b/app/src/main/java/com/planify/mobile/ui/MainActivity.kt @@ -0,0 +1,22 @@ +package com.planify.mobile.ui + +import android.os.Bundle +import androidx.activity.ComponentActivity +import androidx.activity.compose.setContent +import androidx.activity.enableEdgeToEdge +import com.planify.mobile.ui.theme.PlanifyTheme +import dagger.hilt.android.AndroidEntryPoint + +@AndroidEntryPoint +class MainActivity : ComponentActivity() { + + override fun onCreate(savedInstanceState: Bundle?) { + super.onCreate(savedInstanceState) + enableEdgeToEdge() + setContent { + PlanifyTheme { + // TODO #6 : PlanifyNavHost() + } + } + } +} diff --git a/app/src/main/java/com/planify/mobile/ui/theme/Theme.kt b/app/src/main/java/com/planify/mobile/ui/theme/Theme.kt new file mode 100644 index 0000000..594ef8e --- /dev/null +++ b/app/src/main/java/com/planify/mobile/ui/theme/Theme.kt @@ -0,0 +1,36 @@ +package com.planify.mobile.ui.theme + +import android.os.Build +import androidx.compose.foundation.isSystemInDarkTheme +import androidx.compose.material3.MaterialTheme +import androidx.compose.material3.darkColorScheme +import androidx.compose.material3.dynamicDarkColorScheme +import androidx.compose.material3.dynamicLightColorScheme +import androidx.compose.material3.lightColorScheme +import androidx.compose.runtime.Composable +import androidx.compose.ui.platform.LocalContext + +private val LightColorScheme = lightColorScheme() +private val DarkColorScheme = darkColorScheme() + +@Composable +fun PlanifyTheme( + darkTheme: Boolean = isSystemInDarkTheme(), + dynamicColor: Boolean = true, + content: @Composable () -> Unit +) { + val colorScheme = when { + dynamicColor && Build.VERSION.SDK_INT >= Build.VERSION_CODES.S -> { + val context = LocalContext.current + if (darkTheme) dynamicDarkColorScheme(context) else dynamicLightColorScheme(context) + } + darkTheme -> DarkColorScheme + else -> LightColorScheme + } + + MaterialTheme( + colorScheme = colorScheme, + typography = Typography, + content = content + ) +} diff --git a/app/src/main/java/com/planify/mobile/ui/theme/Type.kt b/app/src/main/java/com/planify/mobile/ui/theme/Type.kt new file mode 100644 index 0000000..e1e0b28 --- /dev/null +++ b/app/src/main/java/com/planify/mobile/ui/theme/Type.kt @@ -0,0 +1,15 @@ +package com.planify.mobile.ui.theme + +import androidx.compose.material3.Typography +import androidx.compose.ui.text.TextStyle +import androidx.compose.ui.text.font.FontWeight +import androidx.compose.ui.unit.sp + +val Typography = Typography( + bodyLarge = TextStyle( + fontWeight = FontWeight.Normal, + fontSize = 16.sp, + lineHeight = 24.sp, + letterSpacing = 0.5.sp + ) +) diff --git a/build.gradle.kts b/build.gradle.kts new file mode 100644 index 0000000..0adef57 --- /dev/null +++ b/build.gradle.kts @@ -0,0 +1,6 @@ +plugins { + alias(libs.plugins.android.application) apply false + alias(libs.plugins.jetbrains.kotlin.android) apply false + alias(libs.plugins.hilt) apply false + alias(libs.plugins.ksp) apply false +} diff --git a/gradle/libs.versions.toml b/gradle/libs.versions.toml new file mode 100644 index 0000000..d308142 --- /dev/null +++ b/gradle/libs.versions.toml @@ -0,0 +1,58 @@ +[versions] +agp = "8.4.0" +kotlin = "1.9.24" +coreKtx = "1.13.1" +lifecycleRuntimeKtx = "2.8.3" +activityCompose = "1.9.0" +composeBom = "2024.06.00" +hilt = "2.51.1" +hiltNavigationCompose = "1.2.0" +navigationCompose = "2.7.7" +room = "2.6.1" +coroutines = "1.8.1" +okhttp = "4.12.0" +datastore = "1.1.1" +securityCrypto = "1.1.0-alpha06" +workManager = "2.9.0" +junit = "4.13.2" +junitExt = "1.2.1" +espressoCore = "3.6.1" + +[libraries] +androidx-core-ktx = { group = "androidx.core", name = "core-ktx", version.ref = "coreKtx" } +androidx-lifecycle-runtime-ktx = { group = "androidx.lifecycle", name = "lifecycle-runtime-ktx", version.ref = "lifecycleRuntimeKtx" } +androidx-lifecycle-viewmodel-compose = { group = "androidx.lifecycle", name = "lifecycle-viewmodel-compose", version.ref = "lifecycleRuntimeKtx" } +androidx-activity-compose = { group = "androidx.activity", name = "activity-compose", version.ref = "activityCompose" } +androidx-compose-bom = { group = "androidx.compose", name = "compose-bom", version.ref = "composeBom" } +androidx-ui = { group = "androidx.compose.ui", name = "ui" } +androidx-ui-graphics = { group = "androidx.compose.ui", name = "ui-graphics" } +androidx-ui-tooling = { group = "androidx.compose.ui", name = "ui-tooling" } +androidx-ui-tooling-preview = { group = "androidx.compose.ui", name = "ui-tooling-preview" } +androidx-ui-test-manifest = { group = "androidx.compose.ui", name = "ui-test-manifest" } +androidx-ui-test-junit4 = { group = "androidx.compose.ui", name = "ui-test-junit4" } +androidx-material3 = { group = "androidx.compose.material3", name = "material3" } +androidx-material-icons-extended = { group = "androidx.compose.material", name = "material-icons-extended" } +androidx-navigation-compose = { group = "androidx.navigation", name = "navigation-compose", version.ref = "navigationCompose" } +hilt-android = { group = "com.google.dagger", name = "hilt-android", version.ref = "hilt" } +hilt-compiler = { group = "com.google.dagger", name = "hilt-android-compiler", version.ref = "hilt" } +hilt-navigation-compose = { group = "androidx.hilt", name = "hilt-navigation-compose", version.ref = "hiltNavigationCompose" } +hilt-work = { group = "androidx.hilt", name = "hilt-work", version.ref = "hiltNavigationCompose" } +hilt-work-compiler = { group = "androidx.hilt", name = "hilt-compiler", version.ref = "hiltNavigationCompose" } +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" } +kotlinx-coroutines-android = { group = "org.jetbrains.kotlinx", name = "kotlinx-coroutines-android", version.ref = "coroutines" } +okhttp = { group = "com.squareup.okhttp3", name = "okhttp", version.ref = "okhttp" } +okhttp-logging = { group = "com.squareup.okhttp3", name = "logging-interceptor", version.ref = "okhttp" } +datastore-preferences = { group = "androidx.datastore", name = "datastore-preferences", version.ref = "datastore" } +security-crypto = { group = "androidx.security", name = "security-crypto", version.ref = "securityCrypto" } +work-runtime-ktx = { group = "androidx.work", name = "work-runtime-ktx", version.ref = "workManager" } +junit = { group = "junit", name = "junit", version.ref = "junit" } +androidx-junit = { group = "androidx.test.ext", name = "junit", version.ref = "junitExt" } +androidx-espresso-core = { group = "androidx.test.espresso", name = "espresso-core", version.ref = "espressoCore" } + +[plugins] +android-application = { id = "com.android.application", version.ref = "agp" } +jetbrains-kotlin-android = { id = "org.jetbrains.kotlin.android", version.ref = "kotlin" } +hilt = { id = "com.google.dagger.hilt.android", version.ref = "hilt" } +ksp = { id = "com.google.devtools.ksp", version = "1.9.24-1.0.20" } diff --git a/settings.gradle.kts b/settings.gradle.kts new file mode 100644 index 0000000..654bdd7 --- /dev/null +++ b/settings.gradle.kts @@ -0,0 +1,23 @@ +pluginManagement { + repositories { + google { + content { + includeGroupByRegex("com\\.android.*") + includeGroupByRegex("com\\.google.*") + includeGroupByRegex("androidx.*") + } + } + mavenCentral() + gradlePluginPortal() + } +} +dependencyResolutionManagement { + repositoriesMode.set(RepositoriesMode.FAIL_ON_PROJECT_REPOS) + repositories { + google() + mavenCentral() + } +} + +rootProject.name = "Planify Mobile" +include(":app")