-
Notifications
You must be signed in to change notification settings - Fork 0
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Merge branch 'develop' into feat/#16-snackbar
- Loading branch information
Showing
38 changed files
with
939 additions
and
1 deletion.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1 +1,83 @@ | ||
# 35-APPJAM-ANDROID-SPOONY | ||
# SPOONY | ||
<img src="https://github.com/user-attachments/assets/e25de1b2-a2df-465b-a4ff-c6ff8d85b5b4"> | ||
|
||
|
||
**장소의 찐 리스트를 공유하며 신뢰할 수 있는 추천으로 나만의 지도를 완성하는 앱 서비스** | ||
|
||
<br> | ||
|
||
**‘Spoony’** 는 리뷰 작성자의 신뢰도와 영향력에 기반해, 유저가 믿을 수 있는 장소 정보를 탐색하고 공유하며 나만의 찐 리스트 지도를 만들어가는 앱 서비스입니다. | ||
|
||
🌟Spoony와 함께 새로운 장소를 발견하고 나만의 지도를 완성해보세요!🌟 | ||
|
||
<br> | ||
|
||
|
||
> 🥄 **Spoony 만의 특별한 사용법** <br><br> | ||
1️⃣ **장소 등록하고 수저 획득하기**<br> | ||
나만 알고 싶은 맛집, 아늑한 카페, 분위기 좋은 펍 등 찐 **장소를 등록하고 수저를 획득**하세요!<br><br> | ||
2️⃣**신뢰도 높은 찐 리스트 떠먹기**<br> | ||
획득한 수저로 다른 사람의 찐 리스트를 떠먹어 보세요! 원하는 유저를 팔로우하고 로컬 사용자와 지역별 랭킹을 통해 **신뢰도 높은 리뷰**를 확인해보세요.<br><br> | ||
3️⃣ **나만의 지도 완성하기**<br> | ||
떠먹은 리스트 중 **마음에 드는 장소를** 추가해 나만의 **찐 리스트 지도**를 만들어보세요!<br> | ||
<br> | ||
|
||
## CONTRIBUTORS | ||
| 👑박효빈<br/>([@Hyobeen-Park](https://github.com/Hyobeen-Park)) | 한민재<br/>([@angryPodo](https://github.com/angryPodo)) | 안세홍<br/>([@Roel4990](https://github.com/Roel4990)) | 박동민<br/>([@chattymin](https://github.com/chattymin)) | | ||
|:---------------------------------------------------------------------------------------------------------------------------:|:---------------------------------------------------------------------------------------------------------------------------:|:---------------------------------------------------------------------------------------------------------------------------:|:---------------------------------------------------------------------------------------------------------------------------:| | ||
| <img width="200px" src="https://avatars.githubusercontent.com/u/98209004?v=4"/> | <img width="200px" src="https://avatars.githubusercontent.com/u/160750136?v=4"/> | <img width="200px" src="https://avatars.githubusercontent.com/u/93641814?v=4"/> | <img width="200px" src="https://avatars.githubusercontent.com/u/52882799?v=4"/> | | ||
| `메인 지도`<br/>`탐색하기`<br/> | `장소 등록하기`<br/> | `장소 상세 페이지`<br/>`신고하기`<br/> | `멘토`<br/> | ||
|
||
|
||
<br> | ||
|
||
## PACKAGE CONVENTION | ||
|
||
``` | ||
📁 core | ||
┣ 📁 designsystem | ||
┣ 📁 util | ||
┣ 📁 state | ||
┗ 📁navigation | ||
📁 data | ||
┣ 📁 dto | ||
┃ ┣ 📁 response | ||
┃ ┣ 📁 request | ||
┣ 📁 datasource | ||
┣ 📁 datasourceImpl | ||
┣ 📁 di | ||
┣ 📁 local | ||
┣ 📁 mapper | ||
┣ 📁 repositoryImpl | ||
┗ 📁 service | ||
📁 domain | ||
┣ 📁 entity | ||
┗ 📁 repository | ||
📁 presentation | ||
┗ 📁 기능 별 패키징 | ||
``` | ||
|
||
<br> | ||
|
||
## TECH STACK | ||
| Title | Content | | ||
| ------------ |---------------------------------------| | ||
| Architecture | Clean Architecture, MVVM | | ||
| UI Framework | Jetpack Compose | | ||
| Dependency Injection | Hilt | | ||
| Network | Retrofit2, OkHttp | | ||
| Asynchronous Processing | Coroutine, Flow | | ||
| Third Party Library | Coil, Timber, Lottie, Naver Map | | ||
| Other Tools | Discode, Notion, Figma, Slack |\ | ||
</br> | ||
|
||
## Convention | ||
[안드푼스들의 깃 컨벤션](https://creative-suede-cad.notion.site/Git-Convention-4038dc7126e34df6aa042b400284b188?pvs=4) | ||
<br/> | ||
[안드푼스들의 코딩 컨벤션](https://creative-suede-cad.notion.site/Android-Coding-Convention-71015e22d6a44f28b07aa756c81b2cf3?pvs=4) |
266 changes: 266 additions & 0 deletions
266
app/src/main/java/com/spoony/spoony/core/designsystem/component/button/SpoonyButton.kt
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,266 @@ | ||
package com.spoony.spoony.core.designsystem.component.button | ||
|
||
import androidx.compose.foundation.background | ||
import androidx.compose.foundation.clickable | ||
import androidx.compose.foundation.interaction.MutableInteractionSource | ||
import androidx.compose.foundation.interaction.collectIsPressedAsState | ||
import androidx.compose.foundation.layout.Arrangement | ||
import androidx.compose.foundation.layout.Column | ||
import androidx.compose.foundation.layout.PaddingValues | ||
import androidx.compose.foundation.layout.Row | ||
import androidx.compose.foundation.layout.Spacer | ||
import androidx.compose.foundation.layout.fillMaxWidth | ||
import androidx.compose.foundation.layout.padding | ||
import androidx.compose.foundation.layout.size | ||
import androidx.compose.foundation.layout.width | ||
import androidx.compose.foundation.shape.RoundedCornerShape | ||
import androidx.compose.material3.Icon | ||
import androidx.compose.material3.Text | ||
import androidx.compose.runtime.Composable | ||
import androidx.compose.runtime.getValue | ||
import androidx.compose.runtime.remember | ||
import androidx.compose.ui.Alignment | ||
import androidx.compose.ui.Modifier | ||
import androidx.compose.ui.draw.clip | ||
import androidx.compose.ui.graphics.Color | ||
import androidx.compose.ui.res.painterResource | ||
import androidx.compose.ui.tooling.preview.Preview | ||
import androidx.compose.ui.tooling.preview.PreviewParameter | ||
import androidx.compose.ui.tooling.preview.PreviewParameterProvider | ||
import androidx.compose.ui.unit.dp | ||
import com.spoony.spoony.R | ||
import com.spoony.spoony.core.designsystem.theme.SpoonyAndroidTheme | ||
import com.spoony.spoony.core.designsystem.type.ButtonSize | ||
import com.spoony.spoony.core.designsystem.type.ButtonStyle | ||
|
||
@Composable | ||
fun SpoonyButton( | ||
text: String, | ||
size: ButtonSize, | ||
style: ButtonStyle, | ||
onClick: () -> Unit, | ||
modifier: Modifier = Modifier, | ||
enabled: Boolean = true, | ||
icon: (@Composable () -> Unit)? = null, | ||
interactionSource: MutableInteractionSource = remember { MutableInteractionSource() } | ||
) { | ||
val isPressed by interactionSource.collectIsPressedAsState() | ||
val spoonyColors = SpoonyAndroidTheme.colors | ||
val spoonyTypography = SpoonyAndroidTheme.typography | ||
val backgroundColor = remember(enabled, isPressed, style) { | ||
when { | ||
!enabled -> when (style) { | ||
ButtonStyle.Primary -> spoonyColors.main100 | ||
ButtonStyle.Secondary -> spoonyColors.gray300 | ||
ButtonStyle.Tertiary -> spoonyColors.gray100 | ||
} | ||
isPressed -> when (style) { | ||
ButtonStyle.Primary -> spoonyColors.main500 | ||
ButtonStyle.Secondary -> spoonyColors.gray800 | ||
ButtonStyle.Tertiary -> spoonyColors.gray100 | ||
} | ||
else -> when (style) { | ||
ButtonStyle.Primary -> spoonyColors.main400 | ||
ButtonStyle.Secondary -> spoonyColors.black | ||
ButtonStyle.Tertiary -> spoonyColors.gray0 | ||
} | ||
} | ||
} | ||
val paddingValues = remember(size) { | ||
when (size) { | ||
ButtonSize.Xlarge, ButtonSize.Large, ButtonSize.Medium, ButtonSize.Small -> PaddingValues(horizontal = 16.dp, vertical = 18.dp) | ||
ButtonSize.Xsmall -> PaddingValues(horizontal = 16.dp, vertical = 12.dp) | ||
} | ||
} | ||
|
||
val textColor = remember(style) { | ||
when (style) { | ||
ButtonStyle.Tertiary -> when { | ||
!enabled -> spoonyColors.gray400 | ||
else -> spoonyColors.gray600 | ||
} | ||
else -> spoonyColors.white | ||
} | ||
} | ||
|
||
val cornerRadius = remember(size) { | ||
when (size) { | ||
ButtonSize.Xlarge -> 8.dp | ||
ButtonSize.Large, ButtonSize.Medium, ButtonSize.Small, ButtonSize.Xsmall -> 10.dp | ||
} | ||
} | ||
Row( | ||
modifier = modifier | ||
.clip(RoundedCornerShape(cornerRadius)) | ||
.background(color = backgroundColor) | ||
.clickable( | ||
enabled = enabled, | ||
indication = null, | ||
interactionSource = interactionSource, | ||
onClick = onClick | ||
) | ||
.padding(paddingValues), | ||
verticalAlignment = Alignment.CenterVertically, | ||
horizontalArrangement = Arrangement.Center | ||
) { | ||
if (icon != null) { | ||
icon() | ||
Spacer(modifier = Modifier.width(8.dp)) | ||
} | ||
Text( | ||
text = text, | ||
color = textColor, | ||
style = SpoonyAndroidTheme.typography.body2b | ||
) | ||
} | ||
} | ||
|
||
private class ButtonStyleProvider : PreviewParameterProvider<ButtonStyle> { | ||
override val values: Sequence<ButtonStyle> = sequenceOf( | ||
ButtonStyle.Primary, | ||
ButtonStyle.Secondary, | ||
ButtonStyle.Tertiary | ||
) | ||
} | ||
|
||
@Preview | ||
@Composable | ||
fun SpoonyButtonEnabledPreview( | ||
@PreviewParameter(ButtonStyleProvider::class) style: ButtonStyle | ||
) { | ||
SpoonyAndroidTheme { | ||
Column( | ||
modifier = Modifier, | ||
verticalArrangement = Arrangement.spacedBy(16.dp) | ||
) { | ||
ButtonSize.entries.forEach { size -> | ||
SpoonyButton( | ||
text = "버튼", | ||
style = style, | ||
size = size, | ||
onClick = { } | ||
) | ||
} | ||
} | ||
} | ||
} | ||
|
||
@Preview | ||
@Composable | ||
fun SpoonyButtonEnabledIconPreview( | ||
@PreviewParameter(ButtonStyleProvider::class) style: ButtonStyle | ||
) { | ||
SpoonyAndroidTheme { | ||
Column( | ||
modifier = Modifier, | ||
verticalArrangement = Arrangement.spacedBy(16.dp) | ||
) { | ||
ButtonSize.entries.forEach { size -> | ||
SpoonyButton( | ||
text = "버튼", | ||
style = style, | ||
size = size, | ||
onClick = { }, | ||
icon = { | ||
Icon( | ||
painter = painterResource(R.drawable.ic_launcher_foreground), | ||
modifier = Modifier.size(32.dp), | ||
contentDescription = "ic_spoon_button", | ||
tint = Color.Unspecified | ||
) | ||
} | ||
) | ||
} | ||
} | ||
} | ||
} | ||
|
||
@Preview | ||
@Composable | ||
fun SpoonyButtonDisabledPreview( | ||
@PreviewParameter(ButtonStyleProvider::class) style: ButtonStyle | ||
) { | ||
SpoonyAndroidTheme { | ||
Column( | ||
modifier = Modifier, | ||
verticalArrangement = Arrangement.spacedBy(16.dp) | ||
) { | ||
ButtonSize.entries.forEach { size -> | ||
SpoonyButton( | ||
text = "버튼", | ||
style = style, | ||
size = size, | ||
enabled = false, | ||
onClick = { } | ||
) | ||
} | ||
} | ||
} | ||
} | ||
|
||
@Preview | ||
@Composable | ||
private fun SpoonyButtonWidthModifierPreview() { | ||
SpoonyAndroidTheme { | ||
SpoonyButton( | ||
text = "떠먹으러 가기", | ||
onClick = {}, | ||
style = ButtonStyle.Secondary, | ||
size = ButtonSize.Xsmall, | ||
modifier = Modifier.width(134.dp) | ||
) | ||
} | ||
} | ||
|
||
@Preview | ||
@Composable | ||
private fun SpoonyButtonTwoButtonPreview() { | ||
SpoonyAndroidTheme { | ||
Column( | ||
verticalArrangement = Arrangement.spacedBy(16.dp) | ||
) { | ||
Row( | ||
modifier = Modifier.fillMaxWidth(), | ||
horizontalArrangement = Arrangement.SpaceBetween | ||
) { | ||
SpoonyButton( | ||
text = "버튼", | ||
onClick = {}, | ||
style = ButtonStyle.Tertiary, | ||
size = ButtonSize.Xsmall, | ||
modifier = Modifier.weight(1f) | ||
) | ||
Spacer(modifier = Modifier.width(13.dp)) | ||
SpoonyButton( | ||
text = "버튼", | ||
onClick = {}, | ||
style = ButtonStyle.Secondary, | ||
size = ButtonSize.Xsmall, | ||
modifier = Modifier.weight(1f) | ||
) | ||
} | ||
Row( | ||
modifier = Modifier.fillMaxWidth(), | ||
horizontalArrangement = Arrangement.SpaceBetween | ||
) { | ||
SpoonyButton( | ||
text = "버튼", | ||
onClick = {}, | ||
style = ButtonStyle.Tertiary, | ||
size = ButtonSize.Xsmall, | ||
enabled = false, | ||
modifier = Modifier.weight(1f) | ||
) | ||
Spacer(modifier = Modifier.width(13.dp)) | ||
SpoonyButton( | ||
text = "버튼", | ||
onClick = {}, | ||
style = ButtonStyle.Secondary, | ||
size = ButtonSize.Xsmall, | ||
enabled = false, | ||
modifier = Modifier.weight(1f) | ||
) | ||
} | ||
} | ||
} | ||
} |
9 changes: 9 additions & 0 deletions
9
app/src/main/java/com/spoony/spoony/core/designsystem/type/ButtonStyles.kt
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,9 @@ | ||
package com.spoony.spoony.core.designsystem.type | ||
|
||
enum class ButtonSize { | ||
Xlarge, Large, Medium, Small, Xsmall | ||
} | ||
|
||
enum class ButtonStyle { | ||
Primary, Secondary, Tertiary | ||
} |
17 changes: 17 additions & 0 deletions
17
app/src/main/java/com/spoony/spoony/core/util/extension/ModifierExt.kt
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,17 @@ | ||
package com.spoony.spoony.core.util.extension | ||
|
||
import androidx.compose.foundation.clickable | ||
import androidx.compose.foundation.interaction.MutableInteractionSource | ||
import androidx.compose.runtime.Composable | ||
import androidx.compose.runtime.remember | ||
import androidx.compose.ui.Modifier | ||
import androidx.compose.ui.composed | ||
|
||
@Composable | ||
inline fun Modifier.noRippleClickable(crossinline onClick: () -> Unit): Modifier = composed { | ||
this.clickable( | ||
indication = null, | ||
interactionSource = remember { MutableInteractionSource() }, | ||
onClick = { onClick() } | ||
) | ||
} |
Oops, something went wrong.