diff --git a/CLAUDE.md b/CLAUDE.md new file mode 100644 index 000000000..ab481915a --- /dev/null +++ b/CLAUDE.md @@ -0,0 +1,9 @@ +# CLAUDE.md + +## Code Style Rules + +### No Inline Imports (FQCN 직접 사용 금지) +- 클래스를 사용할 때 반드시 상단에 `import` 문을 선언하고, 코드 본문에서는 단순 클래스명만 사용할 것 +- `android.app.Activity`처럼 FQCN(Fully Qualified Class Name)을 코드 본문에 직접 작성하지 않을 것 +- Bad: `(context as? android.app.Activity)?.finish()` +- Good: `import android.app.Activity` 후 `(context as? Activity)?.finish()` diff --git a/app/build.gradle.kts b/app/build.gradle.kts index 7fb3c640f..869408005 100644 --- a/app/build.gradle.kts +++ b/app/build.gradle.kts @@ -81,6 +81,7 @@ dependencies { implementation(projects.core.firebaseCrashlytics) implementation(projects.core.firebaseMessaging) implementation(projects.core.composeLocals) + implementation(projects.core.designsystem) implementation(projects.core.work) implementation(projects.data.domain) implementation(projects.data.club) @@ -90,6 +91,9 @@ dependencies { implementation(projects.data.notification) implementation(projects.data.place) implementation(projects.domain.navigation) + implementation(projects.core.navigation) + implementation(libs.navigation3.runtime) + implementation(libs.navigation3.ui) implementation(projects.feature.editDepartments) implementation(projects.feature.editSubscription) implementation(projects.feature.feedback) diff --git a/app/src/main/AndroidManifest.xml b/app/src/main/AndroidManifest.xml index b06a0f8e0..1992fda16 100644 --- a/app/src/main/AndroidManifest.xml +++ b/app/src/main/AndroidManifest.xml @@ -26,6 +26,10 @@ android:usesCleartextTraffic="true" tools:replace="icon, label"> + + + + override fun onCreate(savedInstanceState: android.os.Bundle?) { + super.onCreate(savedInstanceState) + enableEdgeToEdge() + setContent { + KuringCompositionLocalProvider { + KuringTheme { + val backStack = rememberNavBackStack(SplashKey) + NavDisplay( + backStack = backStack, + onBack = { if (backStack.removeLastOrNull() == null) finish() }, + entryProvider = entryProvider { + entryBuilders.forEach { builder -> + with(builder) { provide() } + } + } + ) + } + } + } + } +} diff --git a/app/src/main/java/com/ku_stacks/ku_ring/di/NavigationModule.kt b/app/src/main/java/com/ku_stacks/ku_ring/di/NavigationModule.kt new file mode 100644 index 000000000..a8cd9c6bc --- /dev/null +++ b/app/src/main/java/com/ku_stacks/ku_ring/di/NavigationModule.kt @@ -0,0 +1,14 @@ +package com.ku_stacks.ku_ring.di + +import com.ku_stacks.ku_ring.navigation.EntryBuilderProvider +import dagger.Module +import dagger.hilt.InstallIn +import dagger.hilt.components.SingletonComponent +import dagger.multibindings.Multibinds + +@Module +@InstallIn(SingletonComponent::class) +abstract class NavigationModule { + @Multibinds + abstract fun bindEntryBuilderProviders(): Set +} diff --git a/build-logic/build.gradle.kts b/build-logic/build.gradle.kts index ee11c0ebe..10dadc5fa 100644 --- a/build-logic/build.gradle.kts +++ b/build-logic/build.gradle.kts @@ -73,6 +73,10 @@ gradlePlugin { id = "com.ku_stacks.ku_ring.buildlogic.primitive.common-android" implementationClass = "com.ku_stacks.ku_ring.buildlogic.primitive.CommonAndroidPlugin" } + register("com.ku_stacks.ku_ring.buildlogic.primitive.Navigation3Plugin") { + id = "com.ku_stacks.ku_ring.buildlogic.primitive.navigation3" + implementationClass = "com.ku_stacks.ku_ring.buildlogic.primitive.Navigation3Plugin" + } register("com.ku_stacks.ku_ring.buildlogic.primitive.AndroidTestPlugin") { id = "com.ku_stacks.ku_ring.buildlogic.primitive.android-test" implementationClass = "com.ku_stacks.ku_ring.buildlogic.primitive.AndroidTestPlugin" diff --git a/build-logic/src/main/kotlin/com/ku_stacks/ku_ring/buildlogic/primitive/Navigation3Plugin.kt b/build-logic/src/main/kotlin/com/ku_stacks/ku_ring/buildlogic/primitive/Navigation3Plugin.kt new file mode 100644 index 000000000..7427cd03b --- /dev/null +++ b/build-logic/src/main/kotlin/com/ku_stacks/ku_ring/buildlogic/primitive/Navigation3Plugin.kt @@ -0,0 +1,19 @@ +package com.ku_stacks.ku_ring.buildlogic.primitive + +import com.ku_stacks.ku_ring.buildlogic.dsl.implementation +import com.ku_stacks.ku_ring.buildlogic.dsl.library +import com.ku_stacks.ku_ring.buildlogic.dsl.libs +import org.gradle.api.Plugin +import org.gradle.api.Project +import org.gradle.kotlin.dsl.dependencies + +class Navigation3Plugin : Plugin { + override fun apply(target: Project) = + with(target) { + dependencies { + implementation(libs.library("navigation3-runtime")) + implementation(libs.library("navigation3-ui")) + implementation(libs.library("lifecycle-viewmodel-navigation3")) + } + } +} diff --git a/core/navigation/.gitignore b/core/navigation/.gitignore new file mode 100644 index 000000000..796b96d1c --- /dev/null +++ b/core/navigation/.gitignore @@ -0,0 +1 @@ +/build diff --git a/core/navigation/build.gradle.kts b/core/navigation/build.gradle.kts new file mode 100644 index 000000000..30a928573 --- /dev/null +++ b/core/navigation/build.gradle.kts @@ -0,0 +1,13 @@ +import com.ku_stacks.ku_ring.buildlogic.dsl.setNameSpace + +plugins { + kuring("feature") +} + +android { + setNameSpace("core.navigation") +} + +dependencies { + api(libs.navigation3.runtime) +} diff --git a/core/navigation/consumer-rules.pro b/core/navigation/consumer-rules.pro new file mode 100644 index 000000000..2ce9674dc --- /dev/null +++ b/core/navigation/consumer-rules.pro @@ -0,0 +1,3 @@ +# Keep all @Serializable NavKey implementations for Navigation 3 back stack serialization +-keep @kotlinx.serialization.Serializable class * implements androidx.navigation3.runtime.NavKey { *; } +-keepnames @kotlinx.serialization.Serializable class * implements androidx.navigation3.runtime.NavKey diff --git a/core/navigation/src/main/java/com/ku_stacks/ku_ring/navigation/EntryBuilderProvider.kt b/core/navigation/src/main/java/com/ku_stacks/ku_ring/navigation/EntryBuilderProvider.kt new file mode 100644 index 000000000..0a2f09a06 --- /dev/null +++ b/core/navigation/src/main/java/com/ku_stacks/ku_ring/navigation/EntryBuilderProvider.kt @@ -0,0 +1,8 @@ +package com.ku_stacks.ku_ring.navigation + +import androidx.navigation3.runtime.EntryProviderScope +import androidx.navigation3.runtime.NavKey + +interface EntryBuilderProvider { + fun EntryProviderScope.provide() +} diff --git a/core/navigation/src/main/java/com/ku_stacks/ku_ring/navigation/keys/AppLifecycleKeys.kt b/core/navigation/src/main/java/com/ku_stacks/ku_ring/navigation/keys/AppLifecycleKeys.kt new file mode 100644 index 000000000..05436fbb3 --- /dev/null +++ b/core/navigation/src/main/java/com/ku_stacks/ku_ring/navigation/keys/AppLifecycleKeys.kt @@ -0,0 +1,8 @@ +package com.ku_stacks.ku_ring.navigation.keys + +import androidx.navigation3.runtime.NavKey +import kotlinx.serialization.Serializable + +@Serializable data object SplashKey : NavKey +@Serializable data object OnboardingKey : NavKey +@Serializable data class AuthFlowKey(val entryPoint: String) : NavKey diff --git a/core/navigation/src/main/java/com/ku_stacks/ku_ring/navigation/keys/ContentDetailKeys.kt b/core/navigation/src/main/java/com/ku_stacks/ku_ring/navigation/keys/ContentDetailKeys.kt new file mode 100644 index 000000000..2dc392b29 --- /dev/null +++ b/core/navigation/src/main/java/com/ku_stacks/ku_ring/navigation/keys/ContentDetailKeys.kt @@ -0,0 +1,18 @@ +package com.ku_stacks.ku_ring.navigation.keys + +import androidx.navigation3.runtime.NavKey +import kotlinx.serialization.Serializable + +@Serializable data class NoticeWebKey( + val url: String, + val articleId: String, + val id: String, + val category: String, + val subject: String, +) : NavKey + +@Serializable data class NotionViewKey(val url: String) : NavKey + +@Serializable data object ClubOnboardingKey : NavKey +@Serializable data class ClubDetailKey(val clubId: Int) : NavKey +@Serializable data object ClubSubscriptionKey : NavKey diff --git a/core/navigation/src/main/java/com/ku_stacks/ku_ring/navigation/keys/MainNavigationKeys.kt b/core/navigation/src/main/java/com/ku_stacks/ku_ring/navigation/keys/MainNavigationKeys.kt new file mode 100644 index 000000000..c8583ae44 --- /dev/null +++ b/core/navigation/src/main/java/com/ku_stacks/ku_ring/navigation/keys/MainNavigationKeys.kt @@ -0,0 +1,9 @@ +package com.ku_stacks.ku_ring.navigation.keys + +import androidx.navigation3.runtime.NavKey +import kotlinx.serialization.Serializable + +@Serializable data class MainHubKey(val startTab: String = "Notice") : NavKey +@Serializable data object ArchiveKey : NavKey +@Serializable data object SearchKey : NavKey +@Serializable data object OpenSourceKey : NavKey diff --git a/core/navigation/src/main/java/com/ku_stacks/ku_ring/navigation/keys/UtilityScreenKeys.kt b/core/navigation/src/main/java/com/ku_stacks/ku_ring/navigation/keys/UtilityScreenKeys.kt new file mode 100644 index 000000000..8eb2834ea --- /dev/null +++ b/core/navigation/src/main/java/com/ku_stacks/ku_ring/navigation/keys/UtilityScreenKeys.kt @@ -0,0 +1,11 @@ +package com.ku_stacks.ku_ring.navigation.keys + +import androidx.navigation3.runtime.NavKey +import kotlinx.serialization.Serializable + +@Serializable data object FeedbackKey : NavKey +@Serializable data object EditSubscriptionKey : NavKey +@Serializable data object EditDepartmentsKey : NavKey +@Serializable data object NotificationKey : NavKey +@Serializable data object LibrarySeatKey : NavKey +@Serializable data object KuringBotKey : NavKey diff --git a/domain/navigation/consumer-rules.pro b/domain/navigation/consumer-rules.pro deleted file mode 100644 index e69de29bb..000000000 diff --git a/feature/club/build.gradle.kts b/feature/club/build.gradle.kts index 7e4a7c6de..e3065a127 100644 --- a/feature/club/build.gradle.kts +++ b/feature/club/build.gradle.kts @@ -12,6 +12,7 @@ android { } dependencies { + implementation(projects.core.navigation) implementation(projects.core.designsystem) implementation(projects.core.preferences) implementation(projects.core.ui) diff --git a/feature/club/src/main/java/com/ku_stacks/ku_ring/club/detail/ClubDetailActivity.kt b/feature/club/src/main/java/com/ku_stacks/ku_ring/club/detail/ClubDetailActivity.kt index 013410952..72b9f88ad 100644 --- a/feature/club/src/main/java/com/ku_stacks/ku_ring/club/detail/ClubDetailActivity.kt +++ b/feature/club/src/main/java/com/ku_stacks/ku_ring/club/detail/ClubDetailActivity.kt @@ -4,15 +4,6 @@ import android.content.Context import android.content.Intent import android.os.Bundle import androidx.activity.ComponentActivity -import androidx.activity.compose.setContent -import androidx.activity.enableEdgeToEdge -import androidx.compose.foundation.background -import androidx.compose.foundation.layout.fillMaxSize -import androidx.compose.foundation.layout.safeDrawingPadding -import androidx.compose.ui.Modifier -import androidx.compose.ui.platform.LocalContext -import com.ku_stacks.ku_ring.designsystem.kuringtheme.KuringTheme -import com.ku_stacks.ku_ring.util.navigateToExternalBrowser import dagger.hilt.android.AndroidEntryPoint @AndroidEntryPoint @@ -20,22 +11,9 @@ class ClubDetailActivity : ComponentActivity() { override fun onCreate(savedInstanceState: Bundle?) { super.onCreate(savedInstanceState) - enableEdgeToEdge() - - setContent { - KuringTheme { - val context = LocalContext.current - - ClubDetailScreen( - onBack = ::finish, - onMoveToRecruitmentLink = context::navigateToExternalBrowser, - modifier = Modifier - .background(KuringTheme.colors.background) - .safeDrawingPadding() - .fillMaxSize(), - ) - } - } + val intent = Intent().setClassName(this, "com.ku_stacks.ku_ring.HostActivity") + startActivity(intent) + finish() } companion object { diff --git a/feature/club/src/main/java/com/ku_stacks/ku_ring/club/detail/ClubDetailEntryBuilder.kt b/feature/club/src/main/java/com/ku_stacks/ku_ring/club/detail/ClubDetailEntryBuilder.kt new file mode 100644 index 000000000..5317e7f50 --- /dev/null +++ b/feature/club/src/main/java/com/ku_stacks/ku_ring/club/detail/ClubDetailEntryBuilder.kt @@ -0,0 +1,43 @@ +package com.ku_stacks.ku_ring.club.detail + +import android.app.Activity +import androidx.compose.foundation.background +import androidx.compose.foundation.layout.fillMaxSize +import androidx.compose.foundation.layout.safeDrawingPadding +import androidx.compose.ui.Modifier +import androidx.compose.ui.platform.LocalContext +import androidx.navigation3.runtime.EntryProviderScope +import androidx.navigation3.runtime.NavKey +import com.ku_stacks.ku_ring.designsystem.kuringtheme.KuringTheme +import com.ku_stacks.ku_ring.navigation.EntryBuilderProvider +import com.ku_stacks.ku_ring.navigation.keys.ClubDetailKey +import com.ku_stacks.ku_ring.util.navigateToExternalBrowser +import dagger.Module +import dagger.Provides +import dagger.hilt.InstallIn +import dagger.hilt.components.SingletonComponent +import dagger.multibindings.IntoSet + +class ClubDetailEntryBuilder : EntryBuilderProvider { + override fun EntryProviderScope.provide() { + entry { key -> + val context = LocalContext.current + ClubDetailScreen( + onBack = { (context as? Activity)?.finish() }, + onMoveToRecruitmentLink = context::navigateToExternalBrowser, + modifier = Modifier + .background(KuringTheme.colors.background) + .safeDrawingPadding() + .fillMaxSize(), + ) + } + } +} + +@Module +@InstallIn(SingletonComponent::class) +object ClubDetailEntryBuilderModule { + @Provides + @IntoSet + fun provideClubDetailEntryBuilder(): EntryBuilderProvider = ClubDetailEntryBuilder() +} diff --git a/feature/club/src/main/java/com/ku_stacks/ku_ring/club/onboarding/ClubOnboardingActivity.kt b/feature/club/src/main/java/com/ku_stacks/ku_ring/club/onboarding/ClubOnboardingActivity.kt index 193909a9e..40791a82a 100644 --- a/feature/club/src/main/java/com/ku_stacks/ku_ring/club/onboarding/ClubOnboardingActivity.kt +++ b/feature/club/src/main/java/com/ku_stacks/ku_ring/club/onboarding/ClubOnboardingActivity.kt @@ -4,23 +4,15 @@ import android.content.Context import android.content.Intent import android.os.Bundle import androidx.activity.ComponentActivity -import androidx.activity.compose.setContent -import androidx.activity.enableEdgeToEdge -import androidx.compose.foundation.layout.fillMaxSize -import androidx.compose.ui.Modifier -import com.ku_stacks.ku_ring.designsystem.kuringtheme.KuringTheme import dagger.hilt.android.AndroidEntryPoint @AndroidEntryPoint class ClubOnboardingActivity : ComponentActivity() { override fun onCreate(savedInstanceState: Bundle?) { super.onCreate(savedInstanceState) - enableEdgeToEdge() - setContent { - KuringTheme { - ClubOnboardingScreen(onClose = ::finish, modifier = Modifier.fillMaxSize()) - } - } + val intent = Intent().setClassName(this, "com.ku_stacks.ku_ring.HostActivity") + startActivity(intent) + finish() } companion object { diff --git a/feature/club/src/main/java/com/ku_stacks/ku_ring/club/onboarding/ClubOnboardingEntryBuilder.kt b/feature/club/src/main/java/com/ku_stacks/ku_ring/club/onboarding/ClubOnboardingEntryBuilder.kt new file mode 100644 index 000000000..52e9a5616 --- /dev/null +++ b/feature/club/src/main/java/com/ku_stacks/ku_ring/club/onboarding/ClubOnboardingEntryBuilder.kt @@ -0,0 +1,35 @@ +package com.ku_stacks.ku_ring.club.onboarding + +import android.app.Activity +import androidx.compose.foundation.layout.fillMaxSize +import androidx.compose.ui.Modifier +import androidx.compose.ui.platform.LocalContext +import androidx.navigation3.runtime.EntryProviderScope +import androidx.navigation3.runtime.NavKey +import com.ku_stacks.ku_ring.navigation.EntryBuilderProvider +import com.ku_stacks.ku_ring.navigation.keys.ClubOnboardingKey +import dagger.Module +import dagger.Provides +import dagger.hilt.InstallIn +import dagger.hilt.components.SingletonComponent +import dagger.multibindings.IntoSet + +class ClubOnboardingEntryBuilder : EntryBuilderProvider { + override fun EntryProviderScope.provide() { + entry { + val context = LocalContext.current + ClubOnboardingScreen( + onClose = { (context as? Activity)?.finish() }, + modifier = Modifier.fillMaxSize(), + ) + } + } +} + +@Module +@InstallIn(SingletonComponent::class) +object ClubOnboardingEntryBuilderModule { + @Provides + @IntoSet + fun provideClubOnboardingEntryBuilder(): EntryBuilderProvider = ClubOnboardingEntryBuilder() +} diff --git a/feature/club/src/main/java/com/ku_stacks/ku_ring/club/subscription/ClubSubscriptionActivity.kt b/feature/club/src/main/java/com/ku_stacks/ku_ring/club/subscription/ClubSubscriptionActivity.kt index e45941529..3e025c078 100644 --- a/feature/club/src/main/java/com/ku_stacks/ku_ring/club/subscription/ClubSubscriptionActivity.kt +++ b/feature/club/src/main/java/com/ku_stacks/ku_ring/club/subscription/ClubSubscriptionActivity.kt @@ -4,26 +4,15 @@ import android.content.Context import android.content.Intent import android.os.Bundle import androidx.activity.ComponentActivity -import androidx.activity.compose.setContent -import androidx.activity.enableEdgeToEdge -import com.ku_stacks.ku_ring.designsystem.kuringtheme.KuringTheme import dagger.hilt.android.AndroidEntryPoint @AndroidEntryPoint class ClubSubscriptionActivity : ComponentActivity() { override fun onCreate(savedInstanceState: Bundle?) { super.onCreate(savedInstanceState) - enableEdgeToEdge() - setContent { - KuringTheme { - ClubSubscriptionScreen( - onNavigateUp = ::finish, - onNavigateToClubDetail = { clubId -> - // TODO: 동아리 상세 화면으로 이동하는 로직 구현 - }, - ) - } - } + val intent = Intent().setClassName(this, "com.ku_stacks.ku_ring.HostActivity") + startActivity(intent) + finish() } companion object { diff --git a/feature/club/src/main/java/com/ku_stacks/ku_ring/club/subscription/ClubSubscriptionEntryBuilder.kt b/feature/club/src/main/java/com/ku_stacks/ku_ring/club/subscription/ClubSubscriptionEntryBuilder.kt new file mode 100644 index 000000000..4a620db5f --- /dev/null +++ b/feature/club/src/main/java/com/ku_stacks/ku_ring/club/subscription/ClubSubscriptionEntryBuilder.kt @@ -0,0 +1,33 @@ +package com.ku_stacks.ku_ring.club.subscription + +import android.app.Activity +import androidx.compose.ui.platform.LocalContext +import androidx.navigation3.runtime.EntryProviderScope +import androidx.navigation3.runtime.NavKey +import com.ku_stacks.ku_ring.navigation.EntryBuilderProvider +import com.ku_stacks.ku_ring.navigation.keys.ClubSubscriptionKey +import dagger.Module +import dagger.Provides +import dagger.hilt.InstallIn +import dagger.hilt.components.SingletonComponent +import dagger.multibindings.IntoSet + +class ClubSubscriptionEntryBuilder : EntryBuilderProvider { + override fun EntryProviderScope.provide() { + entry { + val context = LocalContext.current + ClubSubscriptionScreen( + onNavigateUp = { (context as? Activity)?.finish() }, + onNavigateToClubDetail = { }, + ) + } + } +} + +@Module +@InstallIn(SingletonComponent::class) +object ClubSubscriptionEntryBuilderModule { + @Provides + @IntoSet + fun provideClubSubscriptionEntryBuilder(): EntryBuilderProvider = ClubSubscriptionEntryBuilder() +} diff --git a/feature/edit_departments/build.gradle.kts b/feature/edit_departments/build.gradle.kts index edf2ed8f8..b003b377f 100644 --- a/feature/edit_departments/build.gradle.kts +++ b/feature/edit_departments/build.gradle.kts @@ -10,6 +10,7 @@ android { } dependencies { + implementation(projects.core.navigation) implementation(projects.core.util) implementation(projects.core.ui) implementation(projects.core.designsystem) diff --git a/feature/edit_departments/src/main/java/com/ku_stacks/ku_ring/edit_departments/EditDepartmentsActivity.kt b/feature/edit_departments/src/main/java/com/ku_stacks/ku_ring/edit_departments/EditDepartmentsActivity.kt index a81d5f7fe..38de63331 100644 --- a/feature/edit_departments/src/main/java/com/ku_stacks/ku_ring/edit_departments/EditDepartmentsActivity.kt +++ b/feature/edit_departments/src/main/java/com/ku_stacks/ku_ring/edit_departments/EditDepartmentsActivity.kt @@ -4,42 +4,20 @@ import android.app.Activity import android.content.Intent import android.os.Bundle import androidx.activity.ComponentActivity -import androidx.activity.compose.setContent -import androidx.compose.foundation.background -import androidx.compose.foundation.layout.fillMaxSize -import androidx.compose.ui.Modifier -import com.ku_stacks.ku_ring.designsystem.kuringtheme.KuringTheme -import com.ku_stacks.ku_ring.edit_departments.compose.EditDepartmentsScreen import dagger.hilt.android.AndroidEntryPoint @AndroidEntryPoint class EditDepartmentsActivity : ComponentActivity() { override fun onCreate(savedInstanceState: Bundle?) { super.onCreate(savedInstanceState) - setContent { - KuringTheme { - EditDepartmentsScreen( - onClose = ::finish, - modifier = Modifier - .fillMaxSize() - .background(KuringTheme.colors.background), - ) - } - } - } - - override fun finish() { - super.finish() - overridePendingTransition(R.anim.anim_slide_left_enter, R.anim.anim_slide_left_exit) + val intent = Intent().setClassName(this, "com.ku_stacks.ku_ring.HostActivity") + startActivity(intent) + finish() } companion object { fun start(activity: Activity) { - activity.apply { - val intent = Intent(this, EditDepartmentsActivity::class.java) - startActivity(intent) - overridePendingTransition(R.anim.anim_slide_right_enter, R.anim.anim_stay_exit) - } + activity.startActivity(Intent(activity, EditDepartmentsActivity::class.java)) } } -} \ No newline at end of file +} diff --git a/feature/edit_departments/src/main/java/com/ku_stacks/ku_ring/edit_departments/EditDepartmentsEntryBuilder.kt b/feature/edit_departments/src/main/java/com/ku_stacks/ku_ring/edit_departments/EditDepartmentsEntryBuilder.kt new file mode 100644 index 000000000..3204c80ac --- /dev/null +++ b/feature/edit_departments/src/main/java/com/ku_stacks/ku_ring/edit_departments/EditDepartmentsEntryBuilder.kt @@ -0,0 +1,40 @@ +package com.ku_stacks.ku_ring.edit_departments + +import android.app.Activity +import androidx.compose.foundation.background +import androidx.compose.foundation.layout.fillMaxSize +import androidx.compose.ui.Modifier +import androidx.compose.ui.platform.LocalContext +import androidx.navigation3.runtime.EntryProviderScope +import androidx.navigation3.runtime.NavKey +import com.ku_stacks.ku_ring.designsystem.kuringtheme.KuringTheme +import com.ku_stacks.ku_ring.edit_departments.compose.EditDepartmentsScreen +import com.ku_stacks.ku_ring.navigation.EntryBuilderProvider +import com.ku_stacks.ku_ring.navigation.keys.EditDepartmentsKey +import dagger.Module +import dagger.Provides +import dagger.hilt.InstallIn +import dagger.hilt.components.SingletonComponent +import dagger.multibindings.IntoSet + +class EditDepartmentsEntryBuilder : EntryBuilderProvider { + override fun EntryProviderScope.provide() { + entry { + val context = LocalContext.current + EditDepartmentsScreen( + onClose = { (context as? Activity)?.finish() }, + modifier = Modifier + .fillMaxSize() + .background(KuringTheme.colors.background), + ) + } + } +} + +@Module +@InstallIn(SingletonComponent::class) +object EditDepartmentsEntryBuilderModule { + @Provides + @IntoSet + fun provideEditDepartmentsEntryBuilder(): EntryBuilderProvider = EditDepartmentsEntryBuilder() +} diff --git a/feature/edit_subscription/build.gradle.kts b/feature/edit_subscription/build.gradle.kts index 7d322faa7..151fcc4f9 100644 --- a/feature/edit_subscription/build.gradle.kts +++ b/feature/edit_subscription/build.gradle.kts @@ -8,6 +8,7 @@ android { } dependencies { + implementation(projects.core.navigation) implementation(projects.core.util) implementation(projects.core.designsystem) implementation(projects.core.ui) diff --git a/feature/edit_subscription/src/main/java/com/ku_stacks/ku_ring/edit_subscription/EditSubscriptionActivity.kt b/feature/edit_subscription/src/main/java/com/ku_stacks/ku_ring/edit_subscription/EditSubscriptionActivity.kt index 614367e38..64f558c22 100644 --- a/feature/edit_subscription/src/main/java/com/ku_stacks/ku_ring/edit_subscription/EditSubscriptionActivity.kt +++ b/feature/edit_subscription/src/main/java/com/ku_stacks/ku_ring/edit_subscription/EditSubscriptionActivity.kt @@ -3,14 +3,7 @@ package com.ku_stacks.ku_ring.edit_subscription import android.app.Activity import android.content.Intent import android.os.Bundle -import androidx.activity.compose.setContent import androidx.appcompat.app.AppCompatActivity -import androidx.compose.foundation.layout.fillMaxSize -import androidx.compose.ui.Modifier -import com.ku_stacks.ku_ring.designsystem.kuringtheme.KuringTheme -import com.ku_stacks.ku_ring.edit_subscription.compose.EditSubscriptionScreen -import com.ku_stacks.ku_ring.compose.locals.KuringCompositionLocalProvider -import com.ku_stacks.ku_ring.compose.locals.LocalNavigator import dagger.hilt.android.AndroidEntryPoint @AndroidEntryPoint @@ -18,30 +11,9 @@ class EditSubscriptionActivity : AppCompatActivity() { override fun onCreate(savedInstanceState: Bundle?) { super.onCreate(savedInstanceState) - - setContent { - KuringCompositionLocalProvider { - val navigator = LocalNavigator.current - KuringTheme { - EditSubscriptionScreen( - onNavigateToBack = ::finish, - onAddDepartmentButtonClick = { - navigator.navigateToEditSubscribedDepartment(this) - }, - onFinish = { - setResult(RESULT_OK) - finish() - }, - modifier = Modifier.fillMaxSize(), - ) - } - } - } - } - - override fun finish() { - super.finish() - overridePendingTransition(R.anim.anim_slide_left_enter, R.anim.anim_slide_left_exit) + val intent = Intent().setClassName(this, "com.ku_stacks.ku_ring.HostActivity") + startActivity(intent) + finish() } companion object { diff --git a/feature/edit_subscription/src/main/java/com/ku_stacks/ku_ring/edit_subscription/EditSubscriptionEntryBuilder.kt b/feature/edit_subscription/src/main/java/com/ku_stacks/ku_ring/edit_subscription/EditSubscriptionEntryBuilder.kt new file mode 100644 index 000000000..c4dc53cef --- /dev/null +++ b/feature/edit_subscription/src/main/java/com/ku_stacks/ku_ring/edit_subscription/EditSubscriptionEntryBuilder.kt @@ -0,0 +1,42 @@ +package com.ku_stacks.ku_ring.edit_subscription + +import android.app.Activity +import androidx.compose.foundation.layout.fillMaxSize +import androidx.compose.ui.Modifier +import androidx.compose.ui.platform.LocalContext +import androidx.navigation3.runtime.EntryProviderScope +import androidx.navigation3.runtime.NavKey +import com.ku_stacks.ku_ring.compose.locals.LocalNavigator +import com.ku_stacks.ku_ring.edit_subscription.compose.EditSubscriptionScreen +import com.ku_stacks.ku_ring.navigation.EntryBuilderProvider +import com.ku_stacks.ku_ring.navigation.keys.EditSubscriptionKey +import dagger.Module +import dagger.Provides +import dagger.hilt.InstallIn +import dagger.hilt.components.SingletonComponent +import dagger.multibindings.IntoSet + +class EditSubscriptionEntryBuilder : EntryBuilderProvider { + override fun EntryProviderScope.provide() { + entry { + val navigator = LocalNavigator.current + val context = LocalContext.current + EditSubscriptionScreen( + onNavigateToBack = { (context as? Activity)?.finish() }, + onFinish = { (context as? Activity)?.finish() }, + onAddDepartmentButtonClick = { + navigator.navigateToEditSubscribedDepartment(context as Activity) + }, + modifier = Modifier.fillMaxSize(), + ) + } + } +} + +@Module +@InstallIn(SingletonComponent::class) +object EditSubscriptionEntryBuilderModule { + @Provides + @IntoSet + fun provideEditSubscriptionEntryBuilder(): EntryBuilderProvider = EditSubscriptionEntryBuilder() +} diff --git a/feature/feedback/build.gradle.kts b/feature/feedback/build.gradle.kts index 58a614057..51bb4e087 100644 --- a/feature/feedback/build.gradle.kts +++ b/feature/feedback/build.gradle.kts @@ -11,6 +11,7 @@ android { } dependencies { + implementation(projects.core.navigation) implementation(projects.core.util) implementation(projects.core.composeUtil) implementation(projects.core.designsystem) diff --git a/feature/feedback/src/main/java/com/ku_stacks/ku_ring/feedback/feedback/FeedbackActivity.kt b/feature/feedback/src/main/java/com/ku_stacks/ku_ring/feedback/feedback/FeedbackActivity.kt index 219c8369a..f4b096f41 100644 --- a/feature/feedback/src/main/java/com/ku_stacks/ku_ring/feedback/feedback/FeedbackActivity.kt +++ b/feature/feedback/src/main/java/com/ku_stacks/ku_ring/feedback/feedback/FeedbackActivity.kt @@ -3,72 +3,22 @@ package com.ku_stacks.ku_ring.feedback.feedback import android.app.Activity import android.content.Intent import android.os.Bundle -import androidx.activity.compose.setContent -import androidx.activity.viewModels -import androidx.appcompat.app.AppCompatActivity -import androidx.compose.foundation.layout.fillMaxSize -import androidx.compose.ui.Modifier -import androidx.lifecycle.flowWithLifecycle -import androidx.lifecycle.lifecycleScope -import com.ku_stacks.ku_ring.designsystem.kuringtheme.KuringTheme -import com.ku_stacks.ku_ring.feedback.R -import com.ku_stacks.ku_ring.feedback.feedback.compose.FeedbackScreen -import com.ku_stacks.ku_ring.util.showToast +import androidx.activity.ComponentActivity import dagger.hilt.android.AndroidEntryPoint -import kotlinx.coroutines.flow.launchIn -import kotlinx.coroutines.flow.onEach @AndroidEntryPoint -class FeedbackActivity : AppCompatActivity() { - - private val viewModel by viewModels() - +class FeedbackActivity : ComponentActivity() { override fun onCreate(savedInstanceState: Bundle?) { super.onCreate(savedInstanceState) - - setupView() - observeViewModel() - } - - private fun setupView() { - setContent { - KuringTheme { - FeedbackScreen( - viewModel = viewModel, - modifier = Modifier.fillMaxSize(), - ) - } - } - } - - private fun observeViewModel() { - viewModel.quit - .flowWithLifecycle(lifecycle) - .onEach { - finish() - }.launchIn(lifecycleScope) - viewModel.toast - .flowWithLifecycle(lifecycle) - .onEach { - showToast(it) - }.launchIn(lifecycleScope) - viewModel.toastByResource - .flowWithLifecycle(lifecycle) - .onEach { - showToast(getString(it)) - }.launchIn(lifecycleScope) - } - - override fun finish() { - super.finish() - overridePendingTransition(R.anim.anim_slide_left_enter, R.anim.anim_slide_left_exit) + val intent = Intent().setClassName(this, "com.ku_stacks.ku_ring.HostActivity") + startActivity(intent) + finish() } companion object { fun start(activity: Activity) { val intent = Intent(activity, FeedbackActivity::class.java) activity.startActivity(intent) - activity.overridePendingTransition(R.anim.anim_slide_right_enter, R.anim.anim_stay_exit) } } } diff --git a/feature/feedback/src/main/java/com/ku_stacks/ku_ring/feedback/feedback/FeedbackEntryBuilder.kt b/feature/feedback/src/main/java/com/ku_stacks/ku_ring/feedback/feedback/FeedbackEntryBuilder.kt new file mode 100644 index 000000000..8d5f9a446 --- /dev/null +++ b/feature/feedback/src/main/java/com/ku_stacks/ku_ring/feedback/feedback/FeedbackEntryBuilder.kt @@ -0,0 +1,57 @@ +package com.ku_stacks.ku_ring.feedback.feedback + +import android.app.Activity +import android.widget.Toast +import androidx.compose.foundation.layout.fillMaxSize +import androidx.compose.runtime.LaunchedEffect +import androidx.compose.ui.Modifier +import androidx.compose.ui.platform.LocalContext +import androidx.hilt.navigation.compose.hiltViewModel +import androidx.navigation3.runtime.EntryProviderScope +import androidx.navigation3.runtime.NavKey +import com.ku_stacks.ku_ring.feedback.feedback.compose.FeedbackScreen +import com.ku_stacks.ku_ring.navigation.EntryBuilderProvider +import com.ku_stacks.ku_ring.navigation.keys.FeedbackKey +import dagger.Module +import dagger.Provides +import dagger.hilt.InstallIn +import dagger.hilt.components.SingletonComponent +import dagger.multibindings.IntoSet + +class FeedbackEntryBuilder : EntryBuilderProvider { + override fun EntryProviderScope.provide() { + entry { + val viewModel = hiltViewModel() + val context = LocalContext.current + + LaunchedEffect(Unit) { + viewModel.quit.collect { + (context as? Activity)?.finish() + } + } + LaunchedEffect(Unit) { + viewModel.toast.collect { message -> + Toast.makeText(context, message, Toast.LENGTH_SHORT).show() + } + } + LaunchedEffect(Unit) { + viewModel.toastByResource.collect { resId -> + Toast.makeText(context, context.getString(resId), Toast.LENGTH_SHORT).show() + } + } + + FeedbackScreen( + viewModel = viewModel, + modifier = Modifier.fillMaxSize(), + ) + } + } +} + +@Module +@InstallIn(SingletonComponent::class) +object FeedbackEntryBuilderModule { + @Provides + @IntoSet + fun provideFeedbackEntryBuilder(): EntryBuilderProvider = FeedbackEntryBuilder() +} diff --git a/feature/kuringbot/build.gradle.kts b/feature/kuringbot/build.gradle.kts index b08c6bfb2..568bfa269 100644 --- a/feature/kuringbot/build.gradle.kts +++ b/feature/kuringbot/build.gradle.kts @@ -11,6 +11,8 @@ android { } dependencies { + implementation(projects.core.navigation) + implementation(projects.core.composeLocals) implementation(projects.core.designsystem) implementation(projects.core.preferences) implementation(projects.core.composeUtil) diff --git a/feature/kuringbot/src/main/java/com/ku_stacks/ku_ring/kuringbot/KuringBotActivity.kt b/feature/kuringbot/src/main/java/com/ku_stacks/ku_ring/kuringbot/KuringBotActivity.kt index e0e863541..3489caf6a 100644 --- a/feature/kuringbot/src/main/java/com/ku_stacks/ku_ring/kuringbot/KuringBotActivity.kt +++ b/feature/kuringbot/src/main/java/com/ku_stacks/ku_ring/kuringbot/KuringBotActivity.kt @@ -3,37 +3,17 @@ package com.ku_stacks.ku_ring.kuringbot import android.content.Context import android.content.Intent import android.os.Bundle -import androidx.activity.compose.setContent import androidx.appcompat.app.AppCompatActivity -import androidx.compose.foundation.layout.fillMaxSize -import androidx.compose.foundation.layout.imePadding -import androidx.compose.ui.Modifier -import com.ku_stacks.ku_ring.designsystem.kuringtheme.KuringTheme -import com.ku_stacks.ku_ring.kuringbot.compose.KuringBotScreen -import com.ku_stacks.ku_ring.navigation.KuringNavigator import dagger.hilt.android.AndroidEntryPoint -import javax.inject.Inject @AndroidEntryPoint class KuringBotActivity : AppCompatActivity() { - @Inject - lateinit var navigator: KuringNavigator - override fun onCreate(savedInstanceState: Bundle?) { super.onCreate(savedInstanceState) - - setContent { - KuringTheme { - KuringBotScreen( - onBackButtonClick = ::finish, - onMoveToLogin = { navigator.navigateToAuth(this) }, - modifier = Modifier - .imePadding() - .fillMaxSize(), - ) - } - } + val intent = Intent().setClassName(this, "com.ku_stacks.ku_ring.HostActivity") + startActivity(intent) + finish() } companion object { diff --git a/feature/kuringbot/src/main/java/com/ku_stacks/ku_ring/kuringbot/KuringBotEntryBuilder.kt b/feature/kuringbot/src/main/java/com/ku_stacks/ku_ring/kuringbot/KuringBotEntryBuilder.kt new file mode 100644 index 000000000..335498eef --- /dev/null +++ b/feature/kuringbot/src/main/java/com/ku_stacks/ku_ring/kuringbot/KuringBotEntryBuilder.kt @@ -0,0 +1,42 @@ +package com.ku_stacks.ku_ring.kuringbot + +import android.app.Activity +import androidx.compose.foundation.layout.fillMaxSize +import androidx.compose.foundation.layout.imePadding +import androidx.compose.ui.Modifier +import androidx.compose.ui.platform.LocalContext +import androidx.navigation3.runtime.EntryProviderScope +import androidx.navigation3.runtime.NavKey +import com.ku_stacks.ku_ring.compose.locals.LocalNavigator +import com.ku_stacks.ku_ring.kuringbot.compose.KuringBotScreen +import com.ku_stacks.ku_ring.navigation.EntryBuilderProvider +import com.ku_stacks.ku_ring.navigation.keys.KuringBotKey +import dagger.Module +import dagger.Provides +import dagger.hilt.InstallIn +import dagger.hilt.components.SingletonComponent +import dagger.multibindings.IntoSet + +class KuringBotEntryBuilder : EntryBuilderProvider { + override fun EntryProviderScope.provide() { + entry { + val navigator = LocalNavigator.current + val context = LocalContext.current + KuringBotScreen( + onBackButtonClick = { (context as? Activity)?.finish() }, + onMoveToLogin = { navigator.navigateToAuth(context) }, + modifier = Modifier + .imePadding() + .fillMaxSize(), + ) + } + } +} + +@Module +@InstallIn(SingletonComponent::class) +object KuringBotEntryBuilderModule { + @Provides + @IntoSet + fun provideKuringBotEntryBuilder(): EntryBuilderProvider = KuringBotEntryBuilder() +} diff --git a/feature/library/build.gradle.kts b/feature/library/build.gradle.kts index 68f379042..b803d7213 100644 --- a/feature/library/build.gradle.kts +++ b/feature/library/build.gradle.kts @@ -11,6 +11,7 @@ android { dependencies { implementation(projects.core.designsystem) + implementation(projects.core.navigation) implementation(projects.core.util) implementation(projects.data.domain) implementation(projects.data.library) diff --git a/feature/library/src/main/java/com/ku_stacks/ku_ring/library/LibrarySeatActivity.kt b/feature/library/src/main/java/com/ku_stacks/ku_ring/library/LibrarySeatActivity.kt index 75ef3d660..7e9881fd6 100644 --- a/feature/library/src/main/java/com/ku_stacks/ku_ring/library/LibrarySeatActivity.kt +++ b/feature/library/src/main/java/com/ku_stacks/ku_ring/library/LibrarySeatActivity.kt @@ -1,117 +1,27 @@ package com.ku_stacks.ku_ring.library import android.app.Activity -import android.content.ActivityNotFoundException import android.content.Intent -import android.content.pm.PackageManager -import android.net.Uri -import android.os.Build import android.os.Bundle -import android.widget.Toast -import androidx.activity.compose.setContent import androidx.appcompat.app.AppCompatActivity -import androidx.compose.foundation.layout.fillMaxSize -import androidx.compose.ui.Modifier -import com.ku_stacks.ku_ring.designsystem.kuringtheme.KuringTheme -import com.ku_stacks.ku_ring.designsystem.R as DesignR -import com.ku_stacks.ku_ring.library.compose.LibrarySeatScreen import dagger.hilt.android.AndroidEntryPoint -import timber.log.Timber @AndroidEntryPoint class LibrarySeatActivity : AppCompatActivity() { override fun onCreate(savedInstanceState: Bundle?) { super.onCreate(savedInstanceState) - setContent { - KuringTheme { - LibrarySeatScreen( - onNavigateBack = ::finish, - onLaunchLibraryIntent = ::launchLibrary, - modifier = Modifier.fillMaxSize() - ) - } - } - } - - override fun finish() { - super.finish() - if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.UPSIDE_DOWN_CAKE) { - overrideActivityTransition( - OVERRIDE_TRANSITION_CLOSE, - DesignR.anim.anim_slide_left_enter, - DesignR.anim.anim_slide_left_exit - ) - } else { - overridePendingTransition(DesignR.anim.anim_slide_left_enter, DesignR.anim.anim_slide_left_exit) - } - } - - private fun launchLibrary() { - try { - checkKonkukLibraryInstalled() - launchKonkukLibrary() - } catch (e: PackageManager.NameNotFoundException) { - launchPlayStore() - } - } - - private fun checkKonkukLibraryInstalled() { - try { - val packageManager = this.packageManager - packageManager.getPackageInfo( - KU_LIBRARY_PACKAGE_NAME, - PackageManager.MATCH_UNINSTALLED_PACKAGES - ) - } catch (e: PackageManager.NameNotFoundException) { - Timber.e("PackageManager could not find $KU_LIBRARY_PACKAGE_NAME: $e") - throw e - } + val intent = Intent().setClassName(this, "com.ku_stacks.ku_ring.HostActivity") + startActivity(intent) + finish() } - private fun launchKonkukLibrary() { - try { - val intent = Intent().apply { - setClassName(KU_LIBRARY_PACKAGE_NAME, KU_LIBRARY_CLASS_NAME) - } - startActivity(intent) - } catch (e: ActivityNotFoundException) { - Toast.makeText(this, MESSAGE_APP_NOT_FOUND, Toast.LENGTH_SHORT).show() - } - } - - private fun launchPlayStore() { - try { - val playStoreIntent = Intent(Intent.ACTION_VIEW).apply { - data = Uri.parse(KU_LIBRARY_STORE_URI) - } - startActivity(playStoreIntent) - } catch (e: ActivityNotFoundException) { - Toast.makeText(this, MESSAGE_APP_NOT_FOUND, Toast.LENGTH_SHORT).show() - } - } - - companion object { fun start(activity: Activity) { with(activity) { val intent = Intent(this, LibrarySeatActivity::class.java) startActivity(intent) - if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.UPSIDE_DOWN_CAKE) { - overrideActivityTransition( - OVERRIDE_TRANSITION_OPEN, - DesignR.anim.anim_slide_right_enter, - DesignR.anim.anim_stay_exit - ) - } else { - overridePendingTransition(DesignR.anim.anim_slide_right_enter, DesignR.anim.anim_stay_exit) - } } } - - private const val KU_LIBRARY_PACKAGE_NAME = "kr.ac.kku.library" - private const val KU_LIBRARY_CLASS_NAME = "kr.ac.kku.library.MainActivity" - private const val KU_LIBRARY_STORE_URI = "market://details?id=$KU_LIBRARY_PACKAGE_NAME" - private const val MESSAGE_APP_NOT_FOUND = "도서관 앱을 찾을 수 없습니다." } } \ No newline at end of file diff --git a/feature/library/src/main/java/com/ku_stacks/ku_ring/library/LibrarySeatEntryBuilder.kt b/feature/library/src/main/java/com/ku_stacks/ku_ring/library/LibrarySeatEntryBuilder.kt new file mode 100644 index 000000000..4671b1b8d --- /dev/null +++ b/feature/library/src/main/java/com/ku_stacks/ku_ring/library/LibrarySeatEntryBuilder.kt @@ -0,0 +1,75 @@ +package com.ku_stacks.ku_ring.library + +import android.app.Activity +import android.content.ActivityNotFoundException +import android.content.Intent +import android.content.pm.PackageManager +import android.net.Uri +import android.widget.Toast +import androidx.compose.foundation.layout.fillMaxSize +import androidx.compose.ui.Modifier +import androidx.compose.ui.platform.LocalContext +import androidx.navigation3.runtime.EntryProviderScope +import androidx.navigation3.runtime.NavKey +import com.ku_stacks.ku_ring.library.compose.LibrarySeatScreen +import com.ku_stacks.ku_ring.navigation.EntryBuilderProvider +import com.ku_stacks.ku_ring.navigation.keys.LibrarySeatKey +import dagger.Module +import dagger.Provides +import dagger.hilt.InstallIn +import dagger.hilt.components.SingletonComponent +import dagger.multibindings.IntoSet +import timber.log.Timber + +class LibrarySeatEntryBuilder : EntryBuilderProvider { + override fun EntryProviderScope.provide() { + entry { + val context = LocalContext.current + LibrarySeatScreen( + onNavigateBack = { (context as? Activity)?.finish() }, + onLaunchLibraryIntent = { + try { + context.packageManager.getPackageInfo( + KU_LIBRARY_PACKAGE_NAME, + PackageManager.MATCH_UNINSTALLED_PACKAGES + ) + try { + val intent = Intent().apply { + setClassName(KU_LIBRARY_PACKAGE_NAME, KU_LIBRARY_CLASS_NAME) + } + context.startActivity(intent) + } catch (e: ActivityNotFoundException) { + Toast.makeText(context, MESSAGE_APP_NOT_FOUND, Toast.LENGTH_SHORT).show() + } + } catch (e: PackageManager.NameNotFoundException) { + Timber.e("PackageManager could not find $KU_LIBRARY_PACKAGE_NAME: $e") + try { + val playStoreIntent = Intent(Intent.ACTION_VIEW).apply { + data = Uri.parse(KU_LIBRARY_STORE_URI) + } + context.startActivity(playStoreIntent) + } catch (e: ActivityNotFoundException) { + Toast.makeText(context, MESSAGE_APP_NOT_FOUND, Toast.LENGTH_SHORT).show() + } + } + }, + modifier = Modifier.fillMaxSize(), + ) + } + } + + private companion object { + const val KU_LIBRARY_PACKAGE_NAME = "kr.ac.kku.library" + const val KU_LIBRARY_CLASS_NAME = "kr.ac.kku.library.MainActivity" + const val KU_LIBRARY_STORE_URI = "market://details?id=$KU_LIBRARY_PACKAGE_NAME" + const val MESSAGE_APP_NOT_FOUND = "도서관 앱을 찾을 수 없습니다." + } +} + +@Module +@InstallIn(SingletonComponent::class) +object LibrarySeatEntryBuilderModule { + @Provides + @IntoSet + fun provideLibrarySeatEntryBuilder(): EntryBuilderProvider = LibrarySeatEntryBuilder() +} diff --git a/feature/notice_detail/build.gradle.kts b/feature/notice_detail/build.gradle.kts index a4db11517..17d6a19bb 100644 --- a/feature/notice_detail/build.gradle.kts +++ b/feature/notice_detail/build.gradle.kts @@ -21,6 +21,7 @@ dependencies { implementation(projects.domain.noticecomment) implementation(projects.domain.report) implementation(projects.domain.navigation) + implementation(projects.core.navigation) implementation(libs.bundles.compose.interop) } diff --git a/feature/notice_detail/src/main/java/com/ku_stacks/ku_ring/notice_detail/NoticeWebActivity.kt b/feature/notice_detail/src/main/java/com/ku_stacks/ku_ring/notice_detail/NoticeWebActivity.kt index 1a06982f3..ed2ee096f 100644 --- a/feature/notice_detail/src/main/java/com/ku_stacks/ku_ring/notice_detail/NoticeWebActivity.kt +++ b/feature/notice_detail/src/main/java/com/ku_stacks/ku_ring/notice_detail/NoticeWebActivity.kt @@ -4,14 +4,8 @@ import android.app.Activity import android.content.Context import android.content.Intent import android.os.Bundle -import androidx.activity.compose.setContent import androidx.appcompat.app.AppCompatActivity -import androidx.compose.foundation.layout.fillMaxSize -import androidx.compose.ui.Modifier -import androidx.navigation.compose.rememberNavController -import com.ku_stacks.ku_ring.designsystem.kuringtheme.KuringTheme import com.ku_stacks.ku_ring.domain.WebViewNotice -import com.ku_stacks.ku_ring.compose.locals.KuringCompositionLocalProvider import dagger.hilt.android.AndroidEntryPoint @AndroidEntryPoint @@ -19,29 +13,10 @@ class NoticeWebActivity : AppCompatActivity() { override fun onCreate(savedInstanceState: Bundle?) { super.onCreate(savedInstanceState) - - // Deprecated되지 않은 다른 함수가 API 33 이상에서만 사용할 수 있어서 부득이하게 deprecated 함수를 사용 - val webViewNotice = intent.getSerializableExtra(WebViewNotice.EXTRA_KEY) as? WebViewNotice - ?: throw IllegalStateException("WebViewNotice should not be null.") - - setContent { - KuringCompositionLocalProvider { - KuringTheme { - val navController = rememberNavController() - NoticeDetailScreen( - navController = navController, - webViewNotice = webViewNotice, - onClose = ::finish, - modifier = Modifier.fillMaxSize(), - ) - } - } - } - } - - override fun finish() { - super.finish() - overridePendingTransition(R.anim.anim_slide_left_enter, R.anim.anim_slide_left_exit) + val redirectIntent = Intent().setClassName(this, "com.ku_stacks.ku_ring.HostActivity") + intent.extras?.let { redirectIntent.putExtras(it) } + startActivity(redirectIntent) + finish() } companion object { diff --git a/feature/notice_detail/src/main/java/com/ku_stacks/ku_ring/notice_detail/NoticeWebEntryBuilder.kt b/feature/notice_detail/src/main/java/com/ku_stacks/ku_ring/notice_detail/NoticeWebEntryBuilder.kt new file mode 100644 index 000000000..935309afe --- /dev/null +++ b/feature/notice_detail/src/main/java/com/ku_stacks/ku_ring/notice_detail/NoticeWebEntryBuilder.kt @@ -0,0 +1,47 @@ +package com.ku_stacks.ku_ring.notice_detail + +import android.app.Activity +import androidx.compose.foundation.layout.fillMaxSize +import androidx.compose.ui.Modifier +import androidx.compose.ui.platform.LocalContext +import androidx.navigation.compose.rememberNavController +import androidx.navigation3.runtime.EntryProviderScope +import androidx.navigation3.runtime.NavKey +import com.ku_stacks.ku_ring.domain.WebViewNotice +import com.ku_stacks.ku_ring.navigation.EntryBuilderProvider +import com.ku_stacks.ku_ring.navigation.keys.NoticeWebKey +import dagger.Module +import dagger.Provides +import dagger.hilt.InstallIn +import dagger.hilt.components.SingletonComponent +import dagger.multibindings.IntoSet + +class NoticeWebEntryBuilder : EntryBuilderProvider { + override fun EntryProviderScope.provide() { + entry { key -> + val context = LocalContext.current + val webViewNotice = WebViewNotice( + url = key.url, + articleId = key.articleId, + id = key.id.toIntOrNull() ?: 0, + category = key.category, + subject = key.subject, + ) + val navController = rememberNavController() + NoticeDetailScreen( + navController = navController, + webViewNotice = webViewNotice, + onClose = { (context as? Activity)?.finish() }, + modifier = Modifier.fillMaxSize(), + ) + } + } +} + +@Module +@InstallIn(SingletonComponent::class) +object NoticeWebEntryBuilderModule { + @Provides + @IntoSet + fun provideNoticeWebEntryBuilder(): EntryBuilderProvider = NoticeWebEntryBuilder() +} diff --git a/feature/notification/build.gradle.kts b/feature/notification/build.gradle.kts index 12def65e8..b5c70c7f1 100644 --- a/feature/notification/build.gradle.kts +++ b/feature/notification/build.gradle.kts @@ -12,6 +12,8 @@ android { } dependencies { + implementation(projects.core.navigation) + implementation(projects.core.composeLocals) implementation(projects.core.designsystem) implementation(projects.core.preferences) implementation(projects.core.ui) diff --git a/feature/notification/src/main/java/com/ku_stacks/ku_ring/notification/NotificationActivity.kt b/feature/notification/src/main/java/com/ku_stacks/ku_ring/notification/NotificationActivity.kt index 5d2225999..c59a54875 100644 --- a/feature/notification/src/main/java/com/ku_stacks/ku_ring/notification/NotificationActivity.kt +++ b/feature/notification/src/main/java/com/ku_stacks/ku_ring/notification/NotificationActivity.kt @@ -4,40 +4,16 @@ import android.content.Context import android.content.Intent import android.os.Bundle import androidx.activity.ComponentActivity -import androidx.activity.compose.setContent -import androidx.activity.enableEdgeToEdge -import com.ku_stacks.ku_ring.designsystem.kuringtheme.KuringTheme -import com.ku_stacks.ku_ring.domain.Notification -import com.ku_stacks.ku_ring.navigation.KuringNavigator -import com.ku_stacks.ku_ring.notification.compose.innerscreen.NotificationScreen import dagger.hilt.android.AndroidEntryPoint -import javax.inject.Inject @AndroidEntryPoint class NotificationActivity : ComponentActivity() { - @Inject - lateinit var navigator: KuringNavigator override fun onCreate(savedInstanceState: Bundle?) { super.onCreate(savedInstanceState) - enableEdgeToEdge() - setContent { - KuringTheme { - NotificationScreen( - onNavigateUp = ::finish, - onNavigateToEditSubscription = ::navigateToEditSubscription, - onNotificationClick = ::determineNavigationTarget - ) - } - } - } - - private fun navigateToEditSubscription() { - navigator.navigateToEditSubscription(this) - } - - private fun determineNavigationTarget(notification: Notification) { - // TODO: 이동 화면 추가 + val intent = Intent().setClassName(this, "com.ku_stacks.ku_ring.HostActivity") + startActivity(intent) + finish() } companion object { diff --git a/feature/notification/src/main/java/com/ku_stacks/ku_ring/notification/NotificationEntryBuilder.kt b/feature/notification/src/main/java/com/ku_stacks/ku_ring/notification/NotificationEntryBuilder.kt new file mode 100644 index 000000000..50591071f --- /dev/null +++ b/feature/notification/src/main/java/com/ku_stacks/ku_ring/notification/NotificationEntryBuilder.kt @@ -0,0 +1,37 @@ +package com.ku_stacks.ku_ring.notification + +import android.app.Activity +import androidx.compose.ui.platform.LocalContext +import androidx.navigation3.runtime.EntryProviderScope +import androidx.navigation3.runtime.NavKey +import com.ku_stacks.ku_ring.compose.locals.LocalNavigator +import com.ku_stacks.ku_ring.navigation.EntryBuilderProvider +import com.ku_stacks.ku_ring.navigation.keys.NotificationKey +import com.ku_stacks.ku_ring.notification.compose.innerscreen.NotificationScreen +import dagger.Module +import dagger.Provides +import dagger.hilt.InstallIn +import dagger.hilt.components.SingletonComponent +import dagger.multibindings.IntoSet + +class NotificationEntryBuilder : EntryBuilderProvider { + override fun EntryProviderScope.provide() { + entry { + val navigator = LocalNavigator.current + val context = LocalContext.current + NotificationScreen( + onNavigateUp = { (context as? Activity)?.finish() }, + onNavigateToEditSubscription = { navigator.navigateToEditSubscription(context as Activity) }, + onNotificationClick = {}, + ) + } + } +} + +@Module +@InstallIn(SingletonComponent::class) +object NotificationEntryBuilderModule { + @Provides + @IntoSet + fun provideNotificationEntryBuilder(): EntryBuilderProvider = NotificationEntryBuilder() +} diff --git a/feature/notion/build.gradle.kts b/feature/notion/build.gradle.kts index 35f029bbf..b071123a4 100644 --- a/feature/notion/build.gradle.kts +++ b/feature/notion/build.gradle.kts @@ -10,6 +10,7 @@ android { } dependencies { + implementation(projects.core.navigation) implementation(projects.core.util) implementation(projects.core.designsystem) } diff --git a/feature/notion/src/main/java/com/ku_stacks/ku_ring/notion/NotionViewActivity.kt b/feature/notion/src/main/java/com/ku_stacks/ku_ring/notion/NotionViewActivity.kt index 6cd7f19e3..94e08aac9 100644 --- a/feature/notion/src/main/java/com/ku_stacks/ku_ring/notion/NotionViewActivity.kt +++ b/feature/notion/src/main/java/com/ku_stacks/ku_ring/notion/NotionViewActivity.kt @@ -1,41 +1,19 @@ package com.ku_stacks.ku_ring.notion -import android.annotation.SuppressLint import android.app.Activity import android.content.Intent import android.os.Bundle -import androidx.activity.compose.setContent -import androidx.appcompat.app.AppCompatActivity -import androidx.compose.foundation.layout.fillMaxSize -import androidx.compose.ui.Modifier -import com.ku_stacks.ku_ring.designsystem.kuringtheme.KuringTheme -import com.ku_stacks.ku_ring.util.TransitionType -import com.ku_stacks.ku_ring.util.setActivityTransition +import androidx.activity.ComponentActivity +import dagger.hilt.android.AndroidEntryPoint -class NotionViewActivity : AppCompatActivity() { +@AndroidEntryPoint +class NotionViewActivity : ComponentActivity() { - @SuppressLint("SetJavaScriptEnabled") override fun onCreate(savedInstanceState: Bundle?) { super.onCreate(savedInstanceState) - - val url = intent.getStringExtra(NOTION_URL) - setContent { - KuringTheme { - NotionScreen( - url = url, - modifier = Modifier.fillMaxSize(), - ) - } - } - } - - override fun finish() { - super.finish() - setActivityTransition( - TransitionType.CLOSE, - R.anim.anim_slide_left_enter, - R.anim.anim_slide_left_exit - ) + val intent = Intent().setClassName(this, "com.ku_stacks.ku_ring.HostActivity") + startActivity(intent) + finish() } companion object { diff --git a/feature/notion/src/main/java/com/ku_stacks/ku_ring/notion/NotionViewEntryBuilder.kt b/feature/notion/src/main/java/com/ku_stacks/ku_ring/notion/NotionViewEntryBuilder.kt new file mode 100644 index 000000000..767633476 --- /dev/null +++ b/feature/notion/src/main/java/com/ku_stacks/ku_ring/notion/NotionViewEntryBuilder.kt @@ -0,0 +1,32 @@ +package com.ku_stacks.ku_ring.notion + +import androidx.compose.foundation.layout.fillMaxSize +import androidx.compose.ui.Modifier +import androidx.navigation3.runtime.EntryProviderScope +import androidx.navigation3.runtime.NavKey +import com.ku_stacks.ku_ring.navigation.EntryBuilderProvider +import com.ku_stacks.ku_ring.navigation.keys.NotionViewKey +import dagger.Module +import dagger.Provides +import dagger.hilt.InstallIn +import dagger.hilt.components.SingletonComponent +import dagger.multibindings.IntoSet + +class NotionViewEntryBuilder : EntryBuilderProvider { + override fun EntryProviderScope.provide() { + entry { key -> + NotionScreen( + url = key.url, + modifier = Modifier.fillMaxSize(), + ) + } + } +} + +@Module +@InstallIn(SingletonComponent::class) +object NotionViewEntryBuilderModule { + @Provides + @IntoSet + fun provideNotionViewEntryBuilder(): EntryBuilderProvider = NotionViewEntryBuilder() +} diff --git a/gradle/libs.versions.toml b/gradle/libs.versions.toml index 6e39a5bd6..172e9c247 100644 --- a/gradle/libs.versions.toml +++ b/gradle/libs.versions.toml @@ -64,6 +64,7 @@ javax-inject = "1" naver-map = "1.9.0" play-service-location = "21.3.0" naver-map-location = "21.0.2" +navigation3 = "1.0.1" [libraries] # Project-level dependencies @@ -206,6 +207,7 @@ ktor-serialization-kotlinx-json = { module = "io.ktor:ktor-serialization-kotlinx # Other libraries keyboardvisibilityevent = 'net.yslibrary.keyboardvisibilityevent:keyboardvisibilityevent:3.0.0-RC3' leakcanary-android = 'com.squareup.leakcanary:leakcanary-android:2.14' +lifecycle-viewmodel-navigation3 = { module = "androidx.lifecycle:lifecycle-viewmodel-navigation3", version = "2.11.0-alpha03" } pageindicatorview = 'com.romandanylyk:pageindicatorview:1.0.3' shimmer = 'com.facebook.shimmer:shimmer:0.5.0' timber = 'com.jakewharton.timber:timber:5.0.1' @@ -213,6 +215,8 @@ semver = "net.swiftzer.semver:semver:2.1.0" naver-map = { module = "io.github.fornewid:naver-map-compose", version.ref = "naver-map" } play-service-location = { module = "com.google.android.gms:play-services-location", version.ref = "play-service-location" } naver-map-location = { module = "io.github.fornewid:naver-map-location", version.ref = "naver-map-location" } +navigation3-runtime = { module = "androidx.navigation3:navigation3-runtime", version.ref = "navigation3" } +navigation3-ui = { module = "androidx.navigation3:navigation3-ui", version.ref = "navigation3" } [bundles] retrofit = [ diff --git a/settings.gradle.kts b/settings.gradle.kts index d536b106e..3f514735f 100644 --- a/settings.gradle.kts +++ b/settings.gradle.kts @@ -36,6 +36,7 @@ include( ":core:firebase-crashlytics", ":core:firebase-messaging", ":core:compose-locals", + ":core:navigation", // data modules ":data:domain", ":data:domain:testUtils",