diff --git a/app-compose/build.gradle.kts b/app-compose/build.gradle.kts index fa34d3bc3..be3fc11b6 100644 --- a/app-compose/build.gradle.kts +++ b/app-compose/build.gradle.kts @@ -3,6 +3,8 @@ plugins { alias(libs.plugins.suwiki.android.application) alias(libs.plugins.suwiki.android.application.compose) alias(libs.plugins.suwiki.android.hilt) + alias(libs.plugins.google.services) + alias(libs.plugins.firebase.crashlytics) } android { @@ -16,15 +18,7 @@ android { } dependencies { - implementation(projects.presentation) - - implementation(projects.core.android) - implementation(projects.core.model) - implementation(projects.core.common) - implementation(projects.core.network) - implementation(projects.core.security) - implementation(projects.core.database) - implementation(projects.core.ui) + implementation(projects.feature.navigator) implementation(projects.remote.openmajor) implementation(projects.remote.timetable) @@ -48,14 +42,9 @@ dependencies { implementation(projects.data.notice) implementation(projects.data.signup) - implementation(projects.domain.openmajor) - implementation(projects.domain.user) - implementation(projects.domain.signup) - implementation(projects.domain.lectureevaluation.viewerreporter) - implementation(projects.domain.lectureevaluation.my) - implementation(projects.domain.lectureevaluation.editor) - implementation(projects.domain.timetable) - implementation(projects.domain.notice) + implementation(platform(libs.firebase.bom)) + implementation(libs.firebase.crashlytics) + implementation(libs.firebase.analytics) implementation(libs.timber) } diff --git a/app-compose/src/main/AndroidManifest.xml b/app-compose/src/main/AndroidManifest.xml index b81d7d3e4..94776ba9c 100644 --- a/app-compose/src/main/AndroidManifest.xml +++ b/app-compose/src/main/AndroidManifest.xml @@ -1,14 +1,18 @@ - + - - + - \ No newline at end of file + diff --git a/app-compose/src/main/res/values/strings.xml b/app-compose/src/main/res/values/strings.xml index 0537dd83f..e84d9b034 100644 --- a/app-compose/src/main/res/values/strings.xml +++ b/app-compose/src/main/res/values/strings.xml @@ -1,3 +1,3 @@ - Suwiki-Compose - \ No newline at end of file + SUWIKI + diff --git a/app-compose/src/main/res/xml/data_extraction_rules.xml b/app-compose/src/main/res/xml/data_extraction_rules.xml new file mode 100644 index 000000000..7da4b02dc --- /dev/null +++ b/app-compose/src/main/res/xml/data_extraction_rules.xml @@ -0,0 +1,17 @@ + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/build-logic/convention/src/main/java/FeatureComposeConventionPlugin.kt b/build-logic/convention/src/main/java/FeatureComposeConventionPlugin.kt index eaf5459d8..2e1478705 100644 --- a/build-logic/convention/src/main/java/FeatureComposeConventionPlugin.kt +++ b/build-logic/convention/src/main/java/FeatureComposeConventionPlugin.kt @@ -2,6 +2,7 @@ import com.kunize.convention.libs import org.gradle.api.Plugin import org.gradle.api.Project import org.gradle.kotlin.dsl.dependencies +import org.gradle.kotlin.dsl.project internal class FeatureComposeConventionPlugin : Plugin { @@ -14,6 +15,14 @@ internal class FeatureComposeConventionPlugin : Plugin { } dependencies { + "implementation"(project(":core:model")) + "implementation"(project(":core:android")) + "implementation"(project(":core:ui")) + "implementation"(project(":core:designsystem")) + + "implementation"(libs.findBundle("orbit").get()) + + "implementation"(libs.findLibrary("kotlinx.immutable").get()) "implementation"(libs.findLibrary("kotlinx.coroutines.android").get()) "implementation"(libs.findLibrary("kotlinx.coroutines.core").get()) diff --git a/build.gradle.kts b/build.gradle.kts index e96ab67e3..8e2b147ed 100644 --- a/build.gradle.kts +++ b/build.gradle.kts @@ -1,8 +1,11 @@ +import org.jetbrains.kotlin.gradle.tasks.KotlinCompile + // Top-level build file where you can add configuration options common to all sub-projects/modules. @Suppress("DSL_SCOPE_VIOLATION") plugins { alias(libs.plugins.detekt) alias(libs.plugins.ktlint) + alias(libs.plugins.firebase.crashlytics) apply false alias(libs.plugins.android.application) apply false alias(libs.plugins.android.library) apply false alias(libs.plugins.kotlin.android) apply false @@ -15,6 +18,8 @@ plugins { } allprojects { + val projectPath = rootProject.file(".").absolutePath + apply { plugin(rootProject.libs.plugins.detekt.get().pluginId) plugin(rootProject.libs.plugins.ktlint.get().pluginId) @@ -28,6 +33,23 @@ allprojects { config.setFrom(files("$rootDir/detekt-config.yml")) } } + + tasks.withType { + kotlinOptions { + freeCompilerArgs = freeCompilerArgs + listOf( + "-opt-in=kotlin.OptIn", + "-opt-in=kotlin.RequiresOptIn", + ) + freeCompilerArgs = freeCompilerArgs + listOf( + "-P", + "plugin:androidx.compose.compiler.plugins.kotlin:metricsDestination=$projectPath/report/compose-metrics", + ) + freeCompilerArgs = freeCompilerArgs + listOf( + "-P", + "plugin:androidx.compose.compiler.plugins.kotlin:reportsDestination=$projectPath/report/compose-reports", + ) + } + } } buildscript { diff --git a/core/android/build.gradle.kts b/core/android/build.gradle.kts index 86f84904d..46ce5d669 100644 --- a/core/android/build.gradle.kts +++ b/core/android/build.gradle.kts @@ -7,3 +7,10 @@ plugins { android { namespace = "com.suwiki.core.android" } + +dependencies { + implementation(projects.core.model) + + implementation(platform(libs.firebase.bom)) + implementation(libs.firebase.crashlytics) +} diff --git a/core/android/src/main/java/com/suwiki/core/android/ThrowUnknownException.kt b/core/android/src/main/java/com/suwiki/core/android/ThrowUnknownException.kt new file mode 100644 index 000000000..1bf96c61a --- /dev/null +++ b/core/android/src/main/java/com/suwiki/core/android/ThrowUnknownException.kt @@ -0,0 +1,12 @@ +package com.suwiki.core.android + +import com.google.firebase.crashlytics.ktx.crashlytics +import com.google.firebase.ktx.Firebase +import com.suwiki.core.model.exception.UnknownException + +fun throwUnknownException( + e: Throwable, +) { + Firebase.crashlytics.recordException(e) + throw e.message?.let { UnknownException(it) } ?: UnknownException() +} diff --git a/core/designsystem/src/main/java/com/suwiki/core/designsystem/component/bottomnavigation/SuwikiBottomNavigation.kt b/core/designsystem/src/main/java/com/suwiki/core/designsystem/component/bottomnavigation/SuwikiBottomNavigation.kt deleted file mode 100644 index 0518b01b9..000000000 --- a/core/designsystem/src/main/java/com/suwiki/core/designsystem/component/bottomnavigation/SuwikiBottomNavigation.kt +++ /dev/null @@ -1,87 +0,0 @@ -package com.suwiki.core.designsystem.component.bottomnavigation - -import androidx.compose.foundation.background -import androidx.compose.foundation.layout.Arrangement -import androidx.compose.foundation.layout.Box -import androidx.compose.foundation.layout.Column -import androidx.compose.foundation.layout.Row -import androidx.compose.foundation.layout.fillMaxWidth -import androidx.compose.foundation.layout.wrapContentHeight -import androidx.compose.foundation.shape.RoundedCornerShape -import androidx.compose.runtime.Composable -import androidx.compose.runtime.getValue -import androidx.compose.runtime.mutableStateOf -import androidx.compose.runtime.remember -import androidx.compose.runtime.setValue -import androidx.compose.ui.Modifier -import androidx.compose.ui.draw.clip -import androidx.compose.ui.draw.shadow -import androidx.compose.ui.tooling.preview.Preview -import androidx.compose.ui.unit.dp -import com.suwiki.core.designsystem.R -import com.suwiki.core.designsystem.theme.SuwikiTheme -import com.suwiki.core.designsystem.theme.White - -@Composable -fun SuwikiBottomNavigation( - modifier: Modifier = Modifier, - isTimeTableChecked: Boolean, - isEvaluationChecked: Boolean, - isMyInfoChecked: Boolean, - onClickTimeTableItem: () -> Unit = {}, - onClickEvaluationItem: () -> Unit = {}, - onClickMyInfoItem: () -> Unit = {}, -) { - Box( - modifier = modifier - .shadow(elevation = 4.dp) - .clip(RoundedCornerShape(10.dp, 10.dp, 0.dp, 0.dp)) - .background(White) - .fillMaxWidth() - .wrapContentHeight(), - ) { - Row( - horizontalArrangement = Arrangement.SpaceBetween, - ) { - SuwikiBottomNavigationItem( - modifier = Modifier.weight(1f), - isChecked = isTimeTableChecked, - iconId = R.drawable.ic_bottom_navigation_evaluation, - onClickItem = onClickTimeTableItem, - ) - SuwikiBottomNavigationItem( - modifier = Modifier.weight(1f), - isChecked = isEvaluationChecked, - iconId = R.drawable.ic_bottom_navigation_evaluation, - onClickItem = onClickEvaluationItem, - ) - SuwikiBottomNavigationItem( - modifier = Modifier.weight(1f), - isChecked = isMyInfoChecked, - iconId = R.drawable.ic_bottom_navigation_evaluation, - onClickItem = onClickMyInfoItem, - ) - } - } -} - -@Preview(showSystemUi = true) -@Composable -fun SuwikiBottomNavigationPreview() { - var isTimeTableChecked by remember { mutableStateOf(true) } - var isEvaluationChecked by remember { mutableStateOf(false) } - var isMyInfoChecked by remember { mutableStateOf(false) } - - SuwikiTheme { - Column { - SuwikiBottomNavigation( - isTimeTableChecked = isTimeTableChecked, - isEvaluationChecked = isEvaluationChecked, - isMyInfoChecked = isMyInfoChecked, - onClickTimeTableItem = { isTimeTableChecked = !isTimeTableChecked }, - onClickEvaluationItem = { isEvaluationChecked = !isEvaluationChecked }, - onClickMyInfoItem = { isMyInfoChecked = !isMyInfoChecked }, - ) - } - } -} diff --git a/core/designsystem/src/main/java/com/suwiki/core/designsystem/component/bottomnavigation/SuwikiBottomNavigationItem.kt b/core/designsystem/src/main/java/com/suwiki/core/designsystem/component/bottomnavigation/SuwikiBottomNavigationItem.kt deleted file mode 100644 index d7c784f1a..000000000 --- a/core/designsystem/src/main/java/com/suwiki/core/designsystem/component/bottomnavigation/SuwikiBottomNavigationItem.kt +++ /dev/null @@ -1,50 +0,0 @@ -package com.suwiki.core.designsystem.component.bottomnavigation - -import androidx.compose.foundation.layout.padding -import androidx.compose.material3.Icon -import androidx.compose.runtime.Composable -import androidx.compose.runtime.getValue -import androidx.compose.runtime.mutableStateOf -import androidx.compose.runtime.remember -import androidx.compose.runtime.setValue -import androidx.compose.ui.Modifier -import androidx.compose.ui.res.painterResource -import androidx.compose.ui.tooling.preview.Preview -import androidx.compose.ui.unit.dp -import com.suwiki.core.designsystem.R -import com.suwiki.core.designsystem.theme.GrayDA -import com.suwiki.core.designsystem.theme.Primary -import com.suwiki.core.designsystem.theme.SuwikiTheme -import com.suwiki.core.ui.extension.suwikiClickable - -@Composable -fun SuwikiBottomNavigationItem( - modifier: Modifier = Modifier, - isChecked: Boolean, - iconId: Int, - onClickItem: () -> Unit = {}, -) { - val iconColor = if (isChecked) Primary else GrayDA - Icon( - painter = painterResource(id = iconId), - contentDescription = "", - tint = iconColor, - modifier = modifier - .suwikiClickable(onClick = onClickItem) - .padding(vertical = 16.dp, horizontal = 48.dp), - ) -} - -@Preview -@Composable -fun SuwikiBottomNavigationItemPreview() { - var isChecked by remember { mutableStateOf(false) } - - SuwikiTheme { - SuwikiBottomNavigationItem( - isChecked = isChecked, - iconId = R.drawable.ic_bottom_navigation_evaluation, - onClickItem = { isChecked = !isChecked }, - ) - } -} diff --git a/core/designsystem/src/main/java/com/suwiki/core/designsystem/component/toast/SuwikiToast.kt b/core/designsystem/src/main/java/com/suwiki/core/designsystem/component/toast/SuwikiToast.kt new file mode 100644 index 000000000..dd6d74cec --- /dev/null +++ b/core/designsystem/src/main/java/com/suwiki/core/designsystem/component/toast/SuwikiToast.kt @@ -0,0 +1,82 @@ +package com.suwiki.core.designsystem.component.toast + +import androidx.compose.animation.AnimatedVisibility +import androidx.compose.animation.fadeIn +import androidx.compose.animation.fadeOut +import androidx.compose.foundation.background +import androidx.compose.foundation.layout.Box +import androidx.compose.foundation.layout.fillMaxSize +import androidx.compose.foundation.layout.imePadding +import androidx.compose.foundation.layout.padding +import androidx.compose.foundation.layout.wrapContentSize +import androidx.compose.foundation.shape.RoundedCornerShape +import androidx.compose.material3.Surface +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.text.style.TextAlign +import androidx.compose.ui.tooling.preview.Preview +import androidx.compose.ui.unit.dp +import com.suwiki.core.designsystem.theme.Gray95 +import com.suwiki.core.designsystem.theme.SuwikiTheme +import com.suwiki.core.designsystem.theme.White + +@Composable +fun SuwikiToast( + visible: Boolean, + message: String, +) { + AnimatedVisibility( + visible = visible, + enter = fadeIn(), + exit = fadeOut(), + ) { + Box( + modifier = Modifier + .fillMaxSize() + .padding(bottom = 70.dp), + contentAlignment = Alignment.BottomCenter, + ) { + SuwikiToastContent( + modifier = Modifier.imePadding(), + message = message, + ) + } + } +} + +@Composable +private fun SuwikiToastContent( + modifier: Modifier = Modifier, + message: String, +) { + Surface( + modifier = modifier + .wrapContentSize() + .background( + color = Gray95, + shape = RoundedCornerShape(25.dp), + ), + color = Color.Transparent, + ) { + Text( + text = message, + textAlign = TextAlign.Center, + style = SuwikiTheme.typography.body5, + color = White, + modifier = Modifier.padding(16.dp, 10.dp), + ) + } +} + +@Preview +@Composable +fun SuwikiToastPreview() { + SuwikiTheme { + SuwikiToastContent( + message = "text", + ) + } +} diff --git a/core/designsystem/src/main/java/com/suwiki/core/designsystem/component/toast/SuwikiToastView.kt b/core/designsystem/src/main/java/com/suwiki/core/designsystem/component/toast/SuwikiToastView.kt deleted file mode 100644 index 85fe45bc7..000000000 --- a/core/designsystem/src/main/java/com/suwiki/core/designsystem/component/toast/SuwikiToastView.kt +++ /dev/null @@ -1,59 +0,0 @@ -package com.suwiki.core.designsystem.component.toast - -import androidx.compose.foundation.background -import androidx.compose.foundation.layout.Box -import androidx.compose.foundation.layout.fillMaxSize -import androidx.compose.foundation.layout.padding -import androidx.compose.foundation.layout.wrapContentSize -import androidx.compose.foundation.shape.RoundedCornerShape -import androidx.compose.material3.Surface -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.text.style.TextAlign -import androidx.compose.ui.tooling.preview.Preview -import androidx.compose.ui.unit.dp -import com.suwiki.core.designsystem.theme.Gray95 -import com.suwiki.core.designsystem.theme.SuwikiTheme -import com.suwiki.core.designsystem.theme.White - -@Composable -fun SuwikiToastView( - messageText: String, -) { - Box( - modifier = Modifier - .fillMaxSize(), - contentAlignment = Alignment.Center, - ) { - Surface( - modifier = Modifier - .wrapContentSize() - .background( - color = Gray95, - shape = RoundedCornerShape(25.dp), - ), - color = Color.Transparent, - ) { - Text( - text = messageText, - textAlign = TextAlign.Center, - style = SuwikiTheme.typography.body5, - color = White, - modifier = Modifier.padding(16.dp, 10.dp), - ) - } - } -} - -@Preview -@Composable -fun SetViewPreview() { - SuwikiTheme { - SuwikiToastView( - messageText = "text", - ) - } -} diff --git a/core/designsystem/src/main/res/values/themes.xml b/core/designsystem/src/main/res/values/themes.xml new file mode 100644 index 000000000..785c47862 --- /dev/null +++ b/core/designsystem/src/main/res/values/themes.xml @@ -0,0 +1,5 @@ + + + +