Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
7 changes: 2 additions & 5 deletions .github/workflows/pr_checker.yml
Original file line number Diff line number Diff line change
Expand Up @@ -15,10 +15,10 @@ jobs:
- name: Checkout code
uses: actions/checkout@v4

- name: Set up JDK 1.8
- name: Set up JDK 17
uses: actions/setup-java@v4
with:
java-version: 1.8
java-version: '17'
distribution: 'temurin'
cache: gradle

Expand All @@ -39,8 +39,5 @@ jobs:
HFM_BASE_URL: ${{ secrets.BASE_URL }}
run: echo "base.url=\"$BASE_URL\"" >> local.properties

- name: Lint Check
run: ./gradlew ktlintCheck -PcompileSdkVersion=34

- name: Build with Gradle
run: ./gradlew build
29 changes: 18 additions & 11 deletions app/build.gradle.kts
Original file line number Diff line number Diff line change
@@ -1,33 +1,30 @@
plugins {
alias(libs.plugins.android.application)
alias(libs.plugins.kotlin.android)
alias(libs.plugins.kotlin.compose)
alias(libs.plugins.kotlin.serialization)
}

android {
namespace = "com.beombeom.composeex"
compileSdk = 35
compileSdk = 36

defaultConfig {
applicationId = "com.beombeom.composeex"
minSdk = 24
targetSdk = 34
targetSdk = 36
versionCode = 1
versionName = "1.0"

testInstrumentationRunner = "androidx.test.runner.AndroidJUnitRunner"
}

composeOptions {
kotlinCompilerExtensionVersion = "1.5.3"
}


buildTypes {
release {
isMinifyEnabled = false
proguardFiles(
getDefaultProguardFile("proguard-android-optimize.txt"),
"proguard-rules.pro"
"proguard-rules.pro",
)
}
}
Expand All @@ -53,8 +50,10 @@ dependencies {
implementation(libs.koin.android)
implementation(libs.koin.androidx.compose)

// Navigation
implementation(libs.androidx.navigation.compose)
// Navigation3
implementation(libs.androidx.navigation3.runtime)
implementation(libs.androidx.navigation3.ui)
implementation(libs.kotlinx.serialization.json)

// Compose
implementation(libs.androidx.ui)
Expand All @@ -65,9 +64,17 @@ dependencies {

// Compose ViewModel
implementation(libs.androidx.lifecycle.viewmodel)
implementation(libs.lifecycle.viewmodel.navigation3)
implementation(libs.accompanist.systemuicontroller)

// ExoPlayer
implementation(libs.androidx.media3.exoplayer)
implementation(libs.androidx.media3.ui)
}
implementation(libs.navigation3.runtime)
implementation(libs.androidx.navigation3.navigation3.runtime)

// Test
testImplementation(libs.junit)
androidTestImplementation(libs.androidx.junit)
androidTestImplementation(libs.androidx.espresso.core)
}
Original file line number Diff line number Diff line change
@@ -1,13 +1,11 @@
package com.beombeom.composeex

import androidx.test.platform.app.InstrumentationRegistry
import androidx.test.ext.junit.runners.AndroidJUnit4

import androidx.test.platform.app.InstrumentationRegistry
import org.junit.Assert.assertEquals
import org.junit.Test
import org.junit.runner.RunWith

import org.junit.Assert.*

/**
* Instrumented test, which will execute on an Android device.
*
Expand All @@ -21,4 +19,4 @@ class ExampleInstrumentedTest {
val appContext = InstrumentationRegistry.getInstrumentation().targetContext
assertEquals("com.beombeom.composeex", appContext.packageName)
}
}
}
106 changes: 73 additions & 33 deletions app/src/main/java/com/beombeom/composeex/presentation/MainActivity.kt
Original file line number Diff line number Diff line change
Expand Up @@ -20,14 +20,28 @@ import androidx.compose.ui.text.TextStyle
import androidx.compose.ui.unit.em
import androidx.compose.ui.unit.sp
import androidx.lifecycle.viewmodel.compose.viewModel
import androidx.navigation.NavHostController
import androidx.navigation.compose.NavHost
import androidx.navigation.compose.composable
import androidx.navigation.compose.rememberNavController
import androidx.lifecycle.viewmodel.navigation3.rememberViewModelStoreNavEntryDecorator
import androidx.navigation3.runtime.NavBackStack
import androidx.navigation3.runtime.NavKey
import androidx.navigation3.runtime.entryProvider
import androidx.navigation3.runtime.rememberNavBackStack
import androidx.navigation3.runtime.rememberSaveableStateHolderNavEntryDecorator
import androidx.navigation3.ui.NavDisplay
import com.beombeom.composeex.R
import com.beombeom.composeex.presentation.common.CardSection
import com.beombeom.composeex.presentation.common.MainHeader
import com.beombeom.composeex.presentation.examples.bottomSheet.BottomSheetMenu
import com.beombeom.composeex.presentation.examples.bottomSheet.BottomSheetScaffoldEx
import com.beombeom.composeex.presentation.examples.bottomSheet.ModalBottomSheetEx
import com.beombeom.composeex.presentation.examples.dropdown.DropdownMenuEx
import com.beombeom.composeex.presentation.examples.lazyLow.RecyclerViewEx
import com.beombeom.composeex.presentation.examples.pager.PagerEx
import com.beombeom.composeex.presentation.examples.pullToRefresh.FullToRefreshEx
import com.beombeom.composeex.presentation.examples.sideEffect.SideEffectEx
import com.beombeom.composeex.presentation.examples.videoPlayer.VideoPlayerEx
import com.beombeom.composeex.presentation.navigation.ExItem
import com.beombeom.composeex.presentation.navigation.ExNavRoute
import com.beombeom.composeex.presentation.navigation.ExTitles
import com.beombeom.composeex.presentation.util.SetSystemUI

class MainActivity : ComponentActivity() {
Expand All @@ -37,36 +51,63 @@ class MainActivity : ComponentActivity() {
val viewModel = viewModel<MainViewModel>()
Surface(
color = Color.White,
contentColor = Color.Black
contentColor = Color.Black,
) {
val navController = rememberNavController()
NavHost(navController = navController, startDestination = "main") {
composable("main") {
SetSystemUI()
MainScreen(viewModel, navController)
}
// Register routes from ExItem
ExItem.getExList().forEach { item ->
composable(
route = item.route
) {
// Pass navController if subCategory exists
if (item.subCategory.isNullOrEmpty()) {
item.content(navController, it)
} else {
item.content(null, it)
}
val backStack = rememberNavBackStack(ExNavRoute.Main)
NavDisplay(
backStack = backStack,
onBack = { backStack.removeLastOrNull() },
entryDecorators = listOf(
// rememberSaveable 동작 보장 (configuration change, process death 대응)
rememberSaveableStateHolderNavEntryDecorator(),
// ViewModel을 NavEntry 생명주기에 스코프
rememberViewModelStoreNavEntryDecorator(),
),
entryProvider = entryProvider {
entry<ExNavRoute.Main> {
SetSystemUI()
MainScreen(viewModel, backStack)
}
}
}
entry<ExNavRoute.BottomSheetMenu> {
BottomSheetMenu(backStack)
}
entry<ExNavRoute.BottomSheetScaffold> {
BottomSheetScaffoldEx(ExTitles.TITLE_BOTTOM_SHEET_SCAFFOLD)
}
entry<ExNavRoute.ModalBottomSheet> {
ModalBottomSheetEx(ExTitles.TITLE_MODAL_BOTTOM_SHEET)
}
entry<ExNavRoute.Pager> {
PagerEx(ExTitles.TITLE_PAGER)
}
entry<ExNavRoute.RecyclerView> {
RecyclerViewEx(ExTitles.TITLE_RECYCLERVIEW)
}
entry<ExNavRoute.VideoPlayer> {
VideoPlayerEx(ExTitles.TITLE_VIDEO_PLAYER)
}
entry<ExNavRoute.SideEffect> {
SideEffectEx(ExTitles.TITLE_SIDE_EFFECT)
}
entry<ExNavRoute.PullToRefresh> {
FullToRefreshEx(ExTitles.TITLE_PULL_TO_REFRESH)
}
entry<ExNavRoute.DropdownMenu> {
DropdownMenuEx(ExTitles.TITLE_DROPDOWNMENU)
}
},
)
}
}
}
}

@OptIn(ExperimentalFoundationApi::class)
@Composable
fun MainScreen(viewModel: MainViewModel, navController: NavHostController) {
fun MainScreen(
viewModel: MainViewModel,
backStack: NavBackStack<NavKey>,
) {
val context = LocalContext.current
val filteredItems = ExItem.getExList().filter { it.subCategory.isNullOrEmpty() }

Expand All @@ -79,11 +120,10 @@ fun MainScreen(viewModel: MainViewModel, navController: NavHostController) {
items(filteredItems) { example ->
Column(modifier = Modifier.fillMaxWidth()) {
CardSection(
context = context,
exampleTitle = example.title,
exampleDescription = example.description,
onButtonClick = {
navController.navigate("${example.route}?title=${example.title}")
backStack.add(example.route)
},
)
}
Expand All @@ -92,9 +132,9 @@ fun MainScreen(viewModel: MainViewModel, navController: NavHostController) {
}
}


fun getTextStyle(fontSize: Int) = TextStyle(
fontSize = fontSize.sp,
letterSpacing = (-0.01).em,
lineHeight = 1.4.em
)
fun getTextStyle(fontSize: Int) =
TextStyle(
fontSize = fontSize.sp,
letterSpacing = (-0.01).em,
lineHeight = 1.4.em,
)
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,6 @@ import android.app.Application
import androidx.lifecycle.AndroidViewModel
import kotlinx.coroutines.flow.MutableStateFlow

class MainViewModel(application : Application) : AndroidViewModel(application){

class MainViewModel(application: Application) : AndroidViewModel(application) {
val toast = MutableStateFlow("")
}
}
Original file line number Diff line number Diff line change
@@ -1,6 +1,5 @@
package com.beombeom.composeex.presentation.common

import android.content.Context
import android.os.Build
import androidx.compose.foundation.background
import androidx.compose.foundation.layout.Arrangement
Expand Down Expand Up @@ -32,27 +31,28 @@ import com.beombeom.composeex.presentation.util.noRippleClickable
@Composable
fun MainHeader(title: String) {
val context = LocalContext.current
val dynamicColorScheme = if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.S) {
dynamicLightColorScheme(context)
} else {
lightColorScheme()
}
val dynamicColorScheme =
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.S) {
dynamicLightColorScheme(context)
} else {
lightColorScheme()
}

MaterialTheme(
colorScheme = dynamicColorScheme,
typography = Typography()
typography = Typography(),
) {
Box(
modifier = Modifier
.fillMaxWidth()
.background(MaterialTheme.colorScheme.primary)
.background(MaterialTheme.colorScheme.primary),
) {
Row(
modifier = Modifier
.fillMaxWidth()
.height(56.dp)
.padding(horizontal = 20.dp),
verticalAlignment = Alignment.CenterVertically
verticalAlignment = Alignment.CenterVertically,
) {
Spacer(modifier = Modifier.weight(1f))
}
Expand All @@ -62,15 +62,14 @@ fun MainHeader(title: String) {
modifier = Modifier.align(Alignment.Center),
color = MaterialTheme.colorScheme.onPrimary,
style = MaterialTheme.typography.displayMedium,
fontSize = 20.sp
fontSize = 20.sp,
)
}
}
}

@Composable
fun CardSection(
context: Context,
exampleTitle: String,
exampleDescription: String,
onButtonClick: () -> Unit,
Expand All @@ -80,22 +79,22 @@ fun CardSection(
.fillMaxWidth()
.padding(horizontal = 20.dp, vertical = 10.dp),
elevation = CardDefaults.cardElevation(
defaultElevation = 3.dp
defaultElevation = 3.dp,
),
shape = RoundedCornerShape(12.dp),
colors = CardDefaults.cardColors(
containerColor = Color.DarkGray,
contentColor = MaterialTheme.colorScheme.onPrimaryContainer
)
contentColor = MaterialTheme.colorScheme.onPrimaryContainer,
),
) {
Column(
modifier = Modifier.padding(20.dp)
modifier = Modifier.padding(20.dp),
) {
androidx.compose.material.Text(
modifier = Modifier.fillMaxWidth(),
text = exampleTitle,
color = Color.White,
style = getTextStyle(18)
style = getTextStyle(18),
)

Spacer(modifier = Modifier.height(4.dp))
Expand All @@ -113,7 +112,7 @@ fun CardSection(
modifier = Modifier
.fillMaxWidth(),
verticalArrangement = Arrangement.Center,
horizontalAlignment = Alignment.CenterHorizontally
horizontalAlignment = Alignment.CenterHorizontally,
) {
Card(
modifier = Modifier
Expand All @@ -123,18 +122,17 @@ fun CardSection(
shape = RoundedCornerShape(16.dp),
colors = CardDefaults.cardColors(
containerColor = Color.White,
)
),
) {
Text(
modifier = Modifier
.padding(horizontal = 10.dp, vertical = 10.dp),
text = "Go Example",
color = Color.Black,
style = getTextStyle(16)
style = getTextStyle(16),
)
}

}
}
}
}
}
Loading
Loading