Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
67 commits
Select commit Hold shift + click to select a range
e0660d2
feature: Add feature setting module
KYM-P Sep 24, 2025
99ea7db
feature: Create setting screen
KYM-P Sep 24, 2025
7626532
chore : Add padding insets and navigation bar padding
KYM-P Sep 28, 2025
690a8dc
chore: Feat ktlint
KYM-P Sep 28, 2025
0021122
chore: Change SettingItem and VersionItem parameter name
KYM-P Oct 6, 2025
cf1959b
feature: Connect SettingViewModel and screen
KYM-P Oct 6, 2025
35190d8
feature: Add contact click event
KYM-P Oct 6, 2025
436eb25
chore: Feat ktlint
KYM-P Oct 6, 2025
50e5a38
featrue: Change Text in m3 to BasicText
KYM-P Oct 6, 2025
a542a82
feature: Add google oss licenses lib
KYM-P Oct 6, 2025
457ef3d
feature: Add term page and oss licenses page
KYM-P Oct 6, 2025
b447ca7
chore: Feat ktlint
KYM-P Oct 6, 2025
0e5e516
chore: Delete funtion's unusable lamda
KYM-P Oct 6, 2025
6fe7a81
chore: Change URL.kt name to URLConstant.kt
KYM-P Oct 6, 2025
bd1d097
feature: Add Navigation extensions 'goToUrl'
KYM-P Oct 6, 2025
71f2bfd
Merge branch 'refactor/#1042-setting-compose-ui' of https://github.co…
KYM-P Oct 6, 2025
e43fb19
fix: Add import Intent
KYM-P Oct 6, 2025
dca7df5
chore: Delete contentPadding parameter
KYM-P Oct 7, 2025
a65ef69
chore: Delete contentpadding parameter
KYM-P Oct 7, 2025
9e3c697
chore: Change list.forEach to list.joinToString
KYM-P Oct 7, 2025
ceedfec
Revert "chore: Delete contentPadding parameter"
KYM-P Oct 7, 2025
4ca18d9
refactor: Change toast message to snackbar
KYM-P Oct 7, 2025
9333a25
chore: Feat ktlint
KYM-P Oct 7, 2025
7a9ac83
fix: Add systembar padding in snackbarhost
KYM-P Oct 7, 2025
74e3164
fix: Component function can get modifier parameter
KYM-P Oct 7, 2025
c5ba672
chore: Move context util funtion to core
KYM-P Oct 8, 2025
96f1728
chore: Feat ktlint
KYM-P Oct 8, 2025
2c93626
Merge branch 'develop' of https://github.com/BCSDLab/KOIN_ANDROID int…
KYM-P Oct 8, 2025
35cc6d0
chore: Change systembars padding and remeber var
KYM-P Oct 8, 2025
265d576
fix: Apply feature plugins
KYM-P Oct 8, 2025
c040fe8
chore: Delete goToContactUrl extention's argument parameter
KYM-P Oct 8, 2025
ab4e617
chore: Feat ktlint
KYM-P Oct 8, 2025
044b8cc
Merge branch 'refactor/#1042-setting-compose-ui' of https://github.co…
KYM-P Oct 8, 2025
05fb0a3
chore: Delete contentPadding, add modifeir prameter
KYM-P Oct 8, 2025
dd4d1ab
fix: Add systemBarPadding after consumeWindowsInset
KYM-P Oct 8, 2025
77463c7
chore: Feat ktlint
KYM-P Oct 8, 2025
655d5c3
chore: ScreenImpl is private funtion
KYM-P Oct 9, 2025
6ff26aa
fix: SettingTitle connected modifier
KYM-P Oct 9, 2025
93a12fb
feature: Add notification string resource
KYM-P Oct 9, 2025
c40e7e0
feature: Add NorificationSwitchItem component
KYM-P Oct 9, 2025
557d908
feature: Add notification menu string resource
KYM-P Oct 9, 2025
38b8af7
Merge pull request #1093 from BCSDLab/refactor/#1042-setting-term-and…
KYM-P Oct 9, 2025
a03a38a
feature: Add notification itme and switchsubitem components
KYM-P Oct 9, 2025
6cb39f1
feature: Add notification screen
KYM-P Oct 9, 2025
810e445
feature: Connect setting screen and notification screen
KYM-P Oct 9, 2025
c18cfc0
chore: Add component padding
KYM-P Oct 9, 2025
f7add57
chore: Feat ktlint
KYM-P Oct 9, 2025
b1e49eb
fix: Change notification appbar text
KYM-P Oct 9, 2025
ae7541b
chore: Add notification viewmodel
KYM-P Oct 9, 2025
e4a8959
feature: Add login snackbar
KYM-P Oct 9, 2025
f501bb0
Merge branch 'refactor/#1042-setting-notification-ui' of https://gith…
KYM-P Oct 9, 2025
54533ab
chore: Feat ktlint
KYM-P Oct 9, 2025
f96d581
Merge branch 'refactor/#1042-setting-notification-ui' of https://gith…
KYM-P Oct 9, 2025
a097ecb
chore: Feat ktlint
KYM-P Oct 9, 2025
75071b2
Merge branch 'refactor/#1042-setting-notification-ui' of https://gith…
KYM-P Oct 9, 2025
73323aa
feature: Connect screen and viewmodel
KYM-P Oct 9, 2025
869382c
chore: Feat ktlint
KYM-P Oct 9, 2025
b7f0821
Merge pull request #1095 from BCSDLab/refactor/#1042-setting-notifica…
KYM-P Oct 9, 2025
2f68241
chore: Delete URLConstant object
KYM-P Oct 12, 2025
df8bd10
chore: Delete Init permitted variable and Add isTypePermitted util
KYM-P Oct 12, 2025
4dabc23
fix: Fix unmatched type
KYM-P Oct 12, 2025
045bd17
chore: Feat ktlint
KYM-P Oct 12, 2025
8f04f16
feature: Apply fastForEach
KYM-P Oct 27, 2025
1230a0a
Merge pull request #1098 from BCSDLab/refactor/#1042-setting-notifica…
KYM-P Oct 27, 2025
a18eb2f
refactor: Remove useless lambda in modifier clickable
KYM-P Oct 27, 2025
ef3f95c
chore: Feat ktlint
KYM-P Oct 27, 2025
9abc59a
Merge pull request #1126 from BCSDLab/refactor/#1042-setting-modifier…
KYM-P Nov 10, 2025
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
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
package `in`.koreatech.koin.core.util

import android.content.Context
import android.content.Intent
import androidx.core.net.toUri

fun Context.goToContactUrl() = startActivity(Intent(Intent.ACTION_VIEW, KOIN_ASK_FORM.toUri()))

const val KOIN_ASK_FORM = "https://forms.gle/Yo1WNR5mLQdi1pMh6"
1 change: 1 addition & 0 deletions feature/setting/.gitignore
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
/build
26 changes: 26 additions & 0 deletions feature/setting/build.gradle.kts
Original file line number Diff line number Diff line change
@@ -0,0 +1,26 @@
plugins {
alias(libs.plugins.koin.feature)
alias(libs.plugins.koin.hilt)
alias(libs.plugins.kotlin.android)
}

android {
namespace = "in.koreatech.koin.feature.setting"
}

dependencies {

implementation(projects.core)
implementation(projects.domain)
implementation(projects.core.designsystem)
implementation(projects.core.navigation)

implementation(libs.androidx.core.ktx)
implementation(libs.androidx.appcompat)
implementation(libs.material)

implementation(libs.kotlinx.collections.immutable)

implementation(libs.timber)
implementation(libs.play.services.oss.licenses)
}
Empty file.
21 changes: 21 additions & 0 deletions feature/setting/proguard-rules.pro
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
# Add project specific ProGuard rules here.
# You can control the set of applied configuration files using the
# proguardFiles setting in build.gradle.
#
# For more details, see
# http://developer.android.com/guide/developing/tools/proguard.html

# If your project uses WebView with JS, uncomment the following
# and specify the fully qualified class name to the JavaScript interface
# class:
#-keepclassmembers class fqcn.of.javascript.interface.for.webview {
# public *;
#}

# Uncomment this to preserve the line number information for
# debugging stack traces.
#-keepattributes SourceFile,LineNumberTable

# If you keep the line number information, uncomment this to
# hide the original source file name.
#-renamesourcefileattribute SourceFile
9 changes: 9 additions & 0 deletions feature/setting/src/main/AndroidManifest.xml
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android">
<application>
<activity
android:name=".ui.SettingActivity"
android:exported="false">
</activity>
</application>
</manifest>
Original file line number Diff line number Diff line change
@@ -0,0 +1,61 @@
package `in`.koreatech.koin.feature.setting.component

import androidx.compose.foundation.background
import androidx.compose.foundation.clickable
import androidx.compose.foundation.layout.Arrangement
import androidx.compose.foundation.layout.Row
import androidx.compose.foundation.layout.fillMaxWidth
import androidx.compose.foundation.layout.padding
import androidx.compose.foundation.text.BasicText
import androidx.compose.material3.HorizontalDivider
import androidx.compose.material3.Icon
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.res.painterResource
import androidx.compose.ui.text.TextStyle
import androidx.compose.ui.tooling.preview.Preview
import androidx.compose.ui.unit.dp
import `in`.koreatech.koin.core.designsystem.theme.KoinTheme
import `in`.koreatech.koin.feature.setting.R

@Composable
fun SettingItem(
text: String,
modifier: Modifier = Modifier,
showIcon: Boolean = false,
textStyle: TextStyle = KoinTheme.typography.regular16,
backgroundColor: Color = KoinTheme.colors.neutral0,
onClick: () -> Unit = {}
) {
Row(
modifier = modifier
.fillMaxWidth()
.background(color = backgroundColor)
.clickable(onClick = onClick)
.padding(vertical = 13.dp, horizontal = 24.dp),
horizontalArrangement = Arrangement.SpaceBetween,
verticalAlignment = Alignment.CenterVertically
) {
BasicText(
text = text,
style = textStyle
)
if (showIcon) {
Icon(
painter = painterResource(R.drawable.ic_arrow_right),
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

ImageVector 사용해주세요

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

https://developer.android.com/develop/ui/compose/graphics/images/compare?hl=ko
그냥 painter 를 써도 vector 이미지면 자동으로 vectorImage 를 통해 그려 주는 거 같습니다.
밑에 ImageVector.vectorResource 를 사용해서 vectorImage 로 주는 게 있긴 한데
Icon(vectorImage = ) 살짝 뜯어보니 결국 내부에서 다시 Icon(painter =) 호출하는 거 보면 그냥 써도 문제 없을 거 같습니다.

contentDescription = ""
)
}
}
HorizontalDivider(color = KoinTheme.colors.neutral100)
}

@Preview(showBackground = true)
@Composable
private fun SettingItemPreview() {
SettingItem(
text = "프로필"
)
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,38 @@
package `in`.koreatech.koin.feature.setting.component

import androidx.compose.foundation.background
import androidx.compose.foundation.layout.fillMaxWidth
import androidx.compose.foundation.layout.padding
import androidx.compose.foundation.text.BasicText
import androidx.compose.runtime.Composable
import androidx.compose.ui.Modifier
import androidx.compose.ui.graphics.Color
import androidx.compose.ui.text.TextStyle
import androidx.compose.ui.tooling.preview.Preview
import androidx.compose.ui.unit.dp
import `in`.koreatech.koin.core.designsystem.theme.KoinTheme

@Composable
fun SettingTitle(
text: String,
modifier: Modifier = Modifier,
textStyle: TextStyle = KoinTheme.typography.medium14,
backgroundColor: Color = KoinTheme.colors.neutral50
) {
BasicText(
modifier = modifier
.fillMaxWidth()
.background(color = backgroundColor)
.padding(vertical = 8.dp, horizontal = 24.dp),
text = text,
style = textStyle
)
}

@Preview(showBackground = true)
@Composable
private fun SettingTitlePreview() {
SettingTitle(
text = "일반"
)
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,102 @@
package `in`.koreatech.koin.feature.setting.component

import androidx.compose.foundation.background
import androidx.compose.foundation.layout.Arrangement
import androidx.compose.foundation.layout.Column
import androidx.compose.foundation.layout.Row
import androidx.compose.foundation.layout.fillMaxWidth
import androidx.compose.foundation.layout.padding
import androidx.compose.foundation.text.BasicText
import androidx.compose.material3.HorizontalDivider
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.res.stringResource
import androidx.compose.ui.text.TextStyle
import androidx.compose.ui.tooling.preview.Preview
import androidx.compose.ui.unit.dp
import `in`.koreatech.koin.core.designsystem.theme.KoinTheme
import `in`.koreatech.koin.feature.setting.R

@Composable
fun SettingVersionItem(
currentVersion: String,
latestVersion: String,
showVersionInfo: Boolean,
modifier: Modifier = Modifier,
textStyle: TextStyle = KoinTheme.typography.regular16,
backgroundColor: Color = KoinTheme.colors.neutral0
) {
Row(
modifier = modifier
.fillMaxWidth()
.background(color = backgroundColor)
.padding(
vertical = if (showVersionInfo) 5.dp else 13.dp,
horizontal = 24.dp
),
horizontalArrangement = Arrangement.SpaceBetween,
verticalAlignment = Alignment.CenterVertically
) {
BasicText(
text = stringResource(R.string.setting_item_app_version),
style = textStyle
)
if (showVersionInfo) {
Column(
horizontalAlignment = Alignment.End
) {
BasicText(
text = currentVersion,
style = KoinTheme.typography.regular14
)
BasicText(
text = if (currentVersion == latestVersion) {
stringResource(R.string.setting_item_newest_version_info)
} else {
stringResource(R.string.setting_item_not_newest_version_info, latestVersion)
},
style = KoinTheme.typography.regular12.copy(
color = if (currentVersion == latestVersion) {
KoinTheme.colors.neutral500
} else {
KoinTheme.colors.primary500
}
)
)
}
}
}
HorizontalDivider(color = KoinTheme.colors.neutral100)
}

@Preview(showBackground = true)
@Composable
private fun SettingVersionItemPreviewVersion() {
SettingVersionItem(
currentVersion = "4.2.3",
latestVersion = "4.2.4",
showVersionInfo = true
)
}

@Preview(showBackground = true)
@Composable
private fun SettingVersionItemPreviewLatest() {
SettingVersionItem(
currentVersion = "4.2.2",
latestVersion = "4.2.2",
showVersionInfo = true
)
}

@Preview(showBackground = true)
@Composable
private fun SettingVersionItemPreviewNotShow() {
SettingVersionItem(
currentVersion = "4.2.2",
latestVersion = "4.2.2",
showVersionInfo = false
)
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,116 @@
package `in`.koreatech.koin.feature.setting.component.switch

import androidx.compose.animation.core.Animatable
import androidx.compose.animation.core.tween
import androidx.compose.foundation.Canvas
import androidx.compose.foundation.background
import androidx.compose.foundation.clickable
import androidx.compose.foundation.interaction.MutableInteractionSource
import androidx.compose.foundation.layout.Box
import androidx.compose.foundation.layout.aspectRatio
import androidx.compose.foundation.layout.height
import androidx.compose.foundation.shape.CircleShape
import androidx.compose.runtime.Composable
import androidx.compose.runtime.LaunchedEffect
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.geometry.CornerRadius
import androidx.compose.ui.geometry.Offset
import androidx.compose.ui.graphics.Color
import androidx.compose.ui.tooling.preview.Preview
import androidx.compose.ui.unit.dp
import `in`.koreatech.koin.core.designsystem.theme.KoinTheme

@Composable
fun KoinSwitch(
checked: Boolean,
onCheckedChange: (Boolean) -> Unit,
modifier: Modifier = Modifier,
switchColors: KoinSwitchColors = KoinSwitchDefaults.koinSwitchColors()
) {
var isChecked by remember(checked) { mutableStateOf(checked) }
val thumbOffset = remember { Animatable(if (isChecked) 1f else 0f) }

LaunchedEffect(isChecked) {
thumbOffset.animateTo(if (isChecked) 1f else 0f, animationSpec = tween(durationMillis = 300))
}

Box(
modifier = modifier
.height(24.dp)
.aspectRatio(2.1f)
.background(Color.Gray, CircleShape)
.clickable(
interactionSource = remember { MutableInteractionSource() },
indication = null
) {
isChecked = !isChecked
onCheckedChange(isChecked)
}
) {
Canvas(modifier = Modifier.matchParentSize()) {
val trackWidth = size.width
val trackHeight = size.height
val thumbMargin = size.height / 8
val thumbRadius = trackHeight / 2 - thumbMargin

// Draw track
drawRoundRect(
color = if (isChecked) switchColors.selectedContainerColor else switchColors.unselectedContainerColor,
size = size,
cornerRadius = CornerRadius(trackHeight / 2, trackHeight / 2)
)

// Draw thumb
val thumbX = (thumbOffset.value * (trackWidth - (thumbRadius + thumbMargin) * 2)) + (thumbRadius + thumbMargin)
drawCircle(
color = if (isChecked) switchColors.selectedContentColor else switchColors.unselectedContentColor,
radius = thumbRadius,
center = Offset(thumbX, trackHeight / 2)
)
}
}
}

object KoinSwitchDefaults {
@Composable
fun koinSwitchColors(
selectedContainerColor: Color = KoinTheme.colors.primary500,
selectedContentColor: Color = Color.White,
unselectedContainerColor: Color = KoinTheme.colors.neutral300,
unselectedContentColor: Color = KoinTheme.colors.neutral0
) = KoinSwitchColors(
selectedContainerColor = selectedContainerColor,
selectedContentColor = selectedContentColor,
unselectedContainerColor = unselectedContainerColor,
unselectedContentColor = unselectedContentColor
)
}

class KoinSwitchColors internal constructor(
val selectedContainerColor: Color,
val selectedContentColor: Color,
val unselectedContainerColor: Color,
val unselectedContentColor: Color
)

@Preview
@Composable
private fun KoinSwitchCheckedPreview() {
KoinSwitch(
checked = true,
onCheckedChange = {}
)
}

@Preview
@Composable
private fun KoinSwitchUnCheckedPreview() {
KoinSwitch(
checked = false,
onCheckedChange = {}
)
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
package `in`.koreatech.koin.feature.setting.constant

val ARTICLE_KEYWORD_URL = "koin://article/activity?fragment=article_keyword"
Loading