Skip to content

Commit

Permalink
Merge pull request #1 from lemoncloud-io/feature/raine-build
Browse files Browse the repository at this point in the history
린트 추가 및 모듈 재구성
  • Loading branch information
raine-lemon authored Aug 22, 2024
2 parents 133af86 + 6b2f390 commit f7c5fe0
Show file tree
Hide file tree
Showing 28 changed files with 115 additions and 64 deletions.
20 changes: 20 additions & 0 deletions .editorconfig
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
root = true

[*]
# 인코딩 방식
charset = utf-8
# 줄바꿈 타입
end_of_line = lf
# 들여쓰기 타입
indent_style = space
# true 경우, 문자 앞의 공백을 제거
trim_trailing_whitespace = true
# ture 경우, 파일을 저장할 때 새 줄로 끝남
insert_final_newline = true
# 최대 길이
max_line_length = 120
# indent_size
indent_size = 4

[*.{kt,kts}]
disabled_rules = import-ordering,comment-spacing
8 changes: 8 additions & 0 deletions .github/pull_request_template.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
# What's Changed




### Memo

별도 메모 사항이 있을 경우 작성
10 changes: 6 additions & 4 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -2,13 +2,15 @@

안드로이드에서 공통적으로 사용될 모듈 저장소

##### 초기화
- 최초로 프로젝트를 다운받은 후 `./init_lint_settings.sh` 를 실행해주세요. commit changes 에 대한 lint를 자동적으로 수행합니다.

## Module

| module | description |
|----------------------------------|---------------------------|
| ui-architecture | mvi 기반 architecture 인터페이스 |
| android-component(Not implement) | android component 관련 유틸리티 |
| module | description |
|---------------------------------------------|---------------------------|
| lemon-core-ui:architecture | mvi 기반 architecture 인터페이스 |
| lemon-core-android:component(Not implement) | android component 관련 유틸리티 |


### UI-Architecture
Expand Down
23 changes: 21 additions & 2 deletions build.gradle.kts
Original file line number Diff line number Diff line change
@@ -1,4 +1,6 @@
// Top-level build file where you can add configuration options common to all sub-projects/modules.
import org.jlleitschuh.gradle.ktlint.reporter.ReporterType
import org.jlleitschuh.gradle.ktlint.tasks.GenerateReportsTask

plugins {
alias(libs.plugins.android.application) apply false
alias(libs.plugins.android.library) apply false
Expand All @@ -10,5 +12,22 @@ plugins {
alias(libs.plugins.kotlin.serialization) apply false
alias(libs.plugins.ksp) apply false
alias(libs.plugins.parcelize) apply false
alias(libs.plugins.ktlint) apply true
}

}
allprojects {
apply {
plugin("org.jlleitschuh.gradle.ktlint")
}
ktlint {
reporters {
reporter(ReporterType.JSON)
reporter(ReporterType.CHECKSTYLE)
}
}
tasks.withType<GenerateReportsTask> {
reportsOutputDirectory.set(
rootProject.layout.buildDirectory.dir("reports/ktlint/${project.name}")
)
}
}
2 changes: 2 additions & 0 deletions gradle/libs.versions.toml
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,7 @@ espresso = "3.0.2"
gradle = "8.5.1"
hilt = "2.49"
junit = "4.13.2"
ktlint = "10.3.0"
kotlin = "2.0.0"
kotlinxCoroutines = "1.8.0"
kotlinxDatetime = "0.5.0"
Expand All @@ -38,6 +39,7 @@ android-library = { id = "com.android.library", version.ref = "gradle" }
android-test = { id = "com.android.test", version.ref = "gradle" }
compose-compiler = { id = "org.jetbrains.kotlin.plugin.compose", version.ref = "kotlin" }
hilt = { id = "com.google.dagger.hilt.android", version.ref = "hilt" }
ktlint = { id = "org.jlleitschuh.gradle.ktlint", version.ref = "ktlint" }
kotlin-android = { id = "org.jetbrains.kotlin.android", version.ref = "kotlin" }
kotlin-jvm = { id = "org.jetbrains.kotlin.jvm", version.ref = "kotlin" }
kotlin-serialization = { id = "org.jetbrains.kotlin.plugin.serialization", version.ref = "kotlin" }
Expand Down
8 changes: 8 additions & 0 deletions init_lint_settings.sh
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
#!/bin/bash

chmod +x "./gradlew"

# pre commit 린트 검사 훅 등록
./gradlew addKtlintCheckGitPreCommitHook

echo "린트 검사 규칙이 적용되었습니다."
File renamed without changes.
20 changes: 20 additions & 0 deletions lemon-core-ui/architecture/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
# UI-Architecture
안드로이드 UI 구조를 효과적으로 빌딩하기 위한 아키텍처 라이브러리. MVI 기반의 아키텍처로 State Event Effect를 제어하여 사용자와 UI간의 상태 및 이벤트 흐름과 사이에 발생하는 이펙트를 효과적으로 처리할 수 있습니다.

### 사용방법

sample 프로젝트 참고
1. `BaseViewModel`를 확장한 `ViewModel` 추가
2. `BaseState`를 확장한 `State` data class 추가
3. `BaseEvent`를 확장한 `Event` sealed interface 추가
4. `BaseEffect`를 확장한 `Effect` sealed interface 추가
5. (필요시) `BaseError`를 확장한 `Error` data class 추가
6. override 되는 `createConfig()` 메서드를 바탕으로 Config 초기 값 설정
7. `BaseViewModel`에 정의한 bind 메서드를 사용하여 event, effect, error 플로우 제어
8. state의 경우 자체 `StateFlow`를 관측하여 UI 상태 감지 가능


### Architecture

![ui-architecture](./assets/ui-architecture.jpeg)

Original file line number Diff line number Diff line change
Expand Up @@ -5,5 +5,5 @@ plugins {
}

android {
namespace = "io.lemon.android.ui.architecture"
}
namespace = "io.lemon.android.core.ui.architecture"
}
File renamed without changes.
File renamed without changes.
8 changes: 3 additions & 5 deletions sample/build.gradle.kts
Original file line number Diff line number Diff line change
Expand Up @@ -10,11 +10,9 @@ plugins {
alias(libs.plugins.lemon.android.kotlin)
}


android{
namespace = "io.lemon.android"
android {
namespace = "io.lemon.android.core"
}
dependencies {
implementation(project(":ui:architecture"))
implementation(project(":lemon-core-ui:architecture"))
}

3 changes: 1 addition & 2 deletions sample/src/main/java/io/lemon/android/MainActivity.kt
Original file line number Diff line number Diff line change
Expand Up @@ -10,9 +10,8 @@ class MainActivity : ComponentActivity() {
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)


setContent {
HomeScreen()
}
}
}
}
33 changes: 16 additions & 17 deletions sample/src/main/java/io/lemon/android/core/home/HomeScreen.kt
Original file line number Diff line number Diff line change
Expand Up @@ -8,11 +8,11 @@ import androidx.compose.foundation.layout.fillMaxSize
import androidx.compose.foundation.layout.padding
import androidx.compose.material3.Button
import androidx.compose.material3.CircularProgressIndicator
import androidx.compose.material3.Text
import androidx.compose.material3.MaterialTheme
import androidx.compose.material3.Scaffold
import androidx.compose.material3.SnackbarHost
import androidx.compose.material3.SnackbarHostState
import androidx.compose.material3.Text
import androidx.compose.runtime.Composable
import androidx.compose.runtime.LaunchedEffect
import androidx.compose.runtime.getValue
Expand All @@ -29,11 +29,10 @@ import io.lemon.android.core.home.data.HomeEvent
import io.lemon.android.core.home.data.HomeState
import io.lemon.android.core.home.data.HomeViewModel


@Composable
fun HomeScreen(
modifier: Modifier = Modifier,
viewModel: HomeViewModel = viewModel()
viewModel: HomeViewModel = viewModel(),
) {
val state: HomeState by viewModel.state.collectAsStateWithLifecycle()
val snackbarHostState = remember { SnackbarHostState() }
Expand All @@ -50,7 +49,7 @@ fun HomeScreen(
modifier = modifier,
snackbarHost = {
SnackbarHost(hostState = snackbarHostState)
}
},
) {
Column(
modifier = modifier
Expand All @@ -59,29 +58,32 @@ fun HomeScreen(
.padding(horizontal = 20.dp)
.padding(it),
verticalArrangement = Arrangement.spacedBy(48.dp, Alignment.CenterVertically),
horizontalAlignment = Alignment.CenterHorizontally
horizontalAlignment = Alignment.CenterHorizontally,
) {
if (state.isLoading) CircularProgressIndicator()
else {
if (state.isLoading) {
CircularProgressIndicator()
} else {
Text(
text = "${state.count}",
fontSize = 36.sp
fontSize = 36.sp,
)
Column(
horizontalAlignment = Alignment.CenterHorizontally,
verticalArrangement = Arrangement.spacedBy(12.dp)
verticalArrangement = Arrangement.spacedBy(12.dp),
) {
Row(
horizontalArrangement = Arrangement.spacedBy(24.dp)
horizontalArrangement = Arrangement.spacedBy(24.dp),
) {
Button(
modifier = modifier.weight(1f),
onClick = { viewModel.onEvent(HomeEvent.OnClickCountUpButton) }) {
onClick = { viewModel.onEvent(HomeEvent.OnClickCountUpButton) },
) {
Text(text = "Count Up")
}
Button(
modifier = modifier.weight(1f),
onClick = { viewModel.onEvent(HomeEvent.OnClickCountDownButton) }) {
onClick = { viewModel.onEvent(HomeEvent.OnClickCountDownButton) },
) {
Text(text = "Count Down")
}
}
Expand All @@ -91,11 +93,8 @@ fun HomeScreen(
}
}


@Composable
@Preview
fun HomeScreenPreview(
modifier: Modifier = Modifier,
) {
fun HomeScreenPreview(modifier: Modifier = Modifier) {
HomeScreen()
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -4,4 +4,4 @@ import io.lemon.android.core.ui.architecture.BaseEffect

sealed interface HomeEffect : BaseEffect {
data class ShowSnackbar(val message: String) : HomeEffect
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -5,4 +5,4 @@ import io.lemon.android.core.ui.architecture.BaseError
data class HomeError(
override val message: String,
override val exception: Throwable?,
) : BaseError
) : BaseError
Original file line number Diff line number Diff line change
Expand Up @@ -2,9 +2,9 @@ package io.lemon.android.core.home.data

import io.lemon.android.core.ui.architecture.BaseEvent


sealed interface HomeEvent : BaseEvent {

data object OnClickCountUpButton : HomeEvent

data object OnClickCountDownButton : HomeEvent
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -2,8 +2,7 @@ package io.lemon.android.core.home.data

import io.lemon.android.core.ui.architecture.BaseState


data class HomeState(
override val isLoading: Boolean = false,
val count: Int = 0,
) : BaseState
) : BaseState
Original file line number Diff line number Diff line change
Expand Up @@ -5,16 +5,14 @@ import io.lemon.android.core.ui.architecture.BaseViewModel

class HomeViewModel : BaseViewModel<HomeState, HomeEvent, HomeEffect, HomeError>() {


override fun createInitialState(): HomeState = HomeState()
override fun createConfig(): Config<HomeEvent> = Config()


init {
bindEvent {
when (it) {
HomeEvent.OnClickCountDownButton -> {
if (state.value.count <= 0) tryEmitError(HomeError(message = "0 이하로 내릴 수 없습니다.", exception = null))
if (state.value.count <= 0) tryEmitError(HomeError(message = "0 이하로 내릴 수 없습니다.", exception = null))
else updateState { copy(count = count - 1) }
}

Expand All @@ -24,5 +22,4 @@ class HomeViewModel : BaseViewModel<HomeState, HomeEvent, HomeEffect, HomeError>

bindError { tryEmitEffect(HomeEffect.ShowSnackbar(it.message)) }
}

}
}
2 changes: 1 addition & 1 deletion settings.gradle.kts
Original file line number Diff line number Diff line change
Expand Up @@ -22,4 +22,4 @@ dependencyResolutionManagement {
}

include(":sample")
include(":ui:architecture")
include(":lemon-core-ui:architecture")
20 changes: 0 additions & 20 deletions ui/architecture/README.md

This file was deleted.

0 comments on commit f7c5fe0

Please sign in to comment.