Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Feat/#57-게시글 목록 조회 UI를 구현한다 #60

Merged
merged 23 commits into from
Mar 24, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
23 commits
Select commit Hold shift + click to select a range
b4868ff
feat : 게시글 등록 모듈 생성
chws0508 Mar 8, 2024
27c6192
feat : 게시글 등록 기능 UI 구현 완료
chws0508 Mar 8, 2024
038eb3c
feat : UI기능 전까지 완료
chws0508 Mar 8, 2024
16fadaa
feat : 커스텀 갤러리 기능 구현
chws0508 Mar 11, 2024
10a6e5f
feat : 갤러리에서 선택한 이미지를 게시글에서 받도록 구현
chws0508 Mar 11, 2024
d7c8136
feat : 게시글 등록 API 연동 구현
chws0508 Mar 11, 2024
a09216d
feat : StringResource 리팩토링
chws0508 Mar 12, 2024
5f024c0
feat : Dependency Graph 모듈 볼수 있는 플러그인 추가
chws0508 Mar 12, 2024
f206048
feat : 화면 회전시 앱이 안보이는 버그 수정
chws0508 Mar 13, 2024
0454238
feat : GetAlbumImagesUseCase로 네이밍 수정
chws0508 Mar 13, 2024
1e7f6a7
feat : GetAlbumImagesUseCase에서 ImagePagingInfo를 주도록 변경
chws0508 Mar 14, 2024
92d3e28
feat : GalleryViewModel Test 작성
chws0508 Mar 14, 2024
700f690
feat : 앱 난독화 적용
chws0508 Mar 15, 2024
7929d99
test : RegisterPostViewModel 테스트 작성
chws0508 Mar 15, 2024
b969197
feat : core-ui 모듈 추가 및 PostTopicUiState core-ui로 이동
chws0508 Mar 18, 2024
4a19142
refactor : Rebase 충돌 수정
chws0508 Mar 18, 2024
6b02cfe
refactor : 모듈을 post에서 postList로 수정
chws0508 Mar 18, 2024
29611b1
refactor : material3 버젼 업
chws0508 Mar 18, 2024
419f456
feat : 게시글 목록 화면 탭 UI 구현
chws0508 Mar 18, 2024
94865c7
feat : Tab에 viewModel 상태 적용
chws0508 Mar 18, 2024
5940514
feat : 게시글 목록 UI 구현 완료
chws0508 Mar 18, 2024
2153afc
feat : Date 계산 로직 도메인으로 이동
chws0508 Mar 19, 2024
022192c
feat : 사진 변경사항 적용
chws0508 Mar 24, 2024
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
2 changes: 1 addition & 1 deletion app/build.gradle.kts
Original file line number Diff line number Diff line change
Expand Up @@ -41,7 +41,7 @@ dependencies {
implementation(libs.androidx.core.splashscreen)
implementation(project(":feature:login"))
implementation(project(":feature:home"))
implementation(project(":feature:post"))
implementation(project(":feature:postlist"))
implementation(project(":feature:mypage"))
implementation(project(":feature:registerpost"))
implementation(project(":feature:gallery"))
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -19,8 +19,8 @@ import com.withpeace.withpeace.feature.home.navigation.HOME_ROUTE
import com.withpeace.withpeace.feature.home.navigation.navigateHome
import com.withpeace.withpeace.feature.mypage.navigation.MY_PAGE_ROUTE
import com.withpeace.withpeace.feature.mypage.navigation.navigateMyPage
import com.withpeace.withpeace.feature.post.navigation.POST_ROUTE
import com.withpeace.withpeace.feature.post.navigation.navigatePost
import com.withpeace.withpeace.feature.postlist.navigation.POST_LIST_ROUTE
import com.withpeace.withpeace.feature.postlist.navigation.navigateToPostList

@Composable
fun MainBottomBar(
Expand Down Expand Up @@ -68,7 +68,7 @@ private fun NavController.navigateToTabScreen(bottomTab: BottomTab) {

when (bottomTab) {
BottomTab.HOME -> navigateHome(tabNavOptions)
BottomTab.POST -> navigatePost(tabNavOptions)
BottomTab.POST -> navigateToPostList(tabNavOptions)
BottomTab.MY_PAGE -> navigateMyPage(tabNavOptions)
}
}
Expand All @@ -89,7 +89,7 @@ enum class BottomTab(
iconUnSelectedResId = R.drawable.ic_bottom_post,
iconSelectedResId = R.drawable.ic_bottom_post_select,
contentDescription = R.string.post,
POST_ROUTE,
POST_LIST_ROUTE,
),
MY_PAGE(
iconUnSelectedResId = R.drawable.ic_bottom_my_page,
Expand All @@ -107,4 +107,4 @@ enum class BottomTab(
return entries.find { it.route == route }
}
}
}
}
7 changes: 5 additions & 2 deletions app/src/main/java/com/withpeace/withpeace/WithpeaceApp.kt
Original file line number Diff line number Diff line change
@@ -1,6 +1,5 @@
package com.withpeace.withpeace

import androidx.compose.foundation.layout.Box
import androidx.compose.foundation.layout.fillMaxSize
import androidx.compose.foundation.layout.height
import androidx.compose.foundation.layout.padding
Expand All @@ -17,6 +16,7 @@ import androidx.compose.ui.unit.dp
import androidx.navigation.NavHostController
import androidx.navigation.compose.currentBackStackEntryAsState
import androidx.navigation.compose.rememberNavController
import com.withpeace.withpeace.core.designsystem.theme.WithpeaceTheme
import com.withpeace.withpeace.navigation.WithpeaceNavHost
import kotlinx.coroutines.launch

Expand Down Expand Up @@ -46,8 +46,11 @@ fun WithpeaceApp(
}
}
},
modifier = Modifier.fillMaxSize().safeDrawingPadding(),
modifier = Modifier
.fillMaxSize()
.safeDrawingPadding(),
snackbarHost = { SnackbarHost(snackBarHostState) },
containerColor = WithpeaceTheme.colors.SystemWhite,
) { innerPadding ->
WithpeaceNavHost(
modifier = Modifier.padding(innerPadding),
Expand Down
13 changes: 4 additions & 9 deletions app/src/main/java/com/withpeace/withpeace/navigation/NavHost.kt
Original file line number Diff line number Diff line change
@@ -1,21 +1,16 @@
package com.withpeace.withpeace.navigation

import androidx.compose.animation.AnimatedVisibility
import androidx.compose.foundation.layout.Box
import androidx.compose.foundation.layout.padding
import androidx.compose.runtime.Composable
import androidx.compose.ui.Modifier
import androidx.navigation.NavHostController
import androidx.navigation.compose.NavHost
import androidx.navigation.compose.rememberNavController
import androidx.navigation.navOptions
import com.withpeace.withpeace.feature.home.navigation.homeNavGraph
import com.withpeace.withpeace.feature.mypage.navigation.myPageNavGraph
import com.withpeace.withpeace.feature.post.navigation.postNavGraph
import com.withpeace.withpeace.feature.gallery.navigation.galleryNavGraph
import com.withpeace.withpeace.feature.gallery.navigation.navigateToGallery
import com.withpeace.withpeace.feature.home.navigation.homeNavGraph
import com.withpeace.withpeace.feature.login.navigation.LOGIN_ROUTE
import com.withpeace.withpeace.feature.login.navigation.loginNavGraph
import com.withpeace.withpeace.feature.mypage.navigation.myPageNavGraph
import com.withpeace.withpeace.feature.postlist.navigation.postListGraph
import com.withpeace.withpeace.feature.registerpost.navigation.IMAGE_LIST_ARGUMENT
import com.withpeace.withpeace.feature.registerpost.navigation.registerPostNavGraph

Expand Down Expand Up @@ -59,7 +54,7 @@ fun WithpeaceNavHost(
onShowSnackBar = onShowSnackBar,
)
homeNavGraph(onShowSnackBar)
postNavGraph(onShowSnackBar)
postListGraph(onShowSnackBar)
myPageNavGraph(onShowSnackBar)
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,7 @@ dependencies {

"implementation"(libs.findLibrary("androidx.activity.compose").get())
"implementation"(libs.findLibrary("androidx.compose.material3").get())
"implementation"(libs.findLibrary("androidx.constraintlayout").get())
"implementation"(libs.findLibrary("androidx.compose.ui").get())
"implementation"(libs.findLibrary("androidx.compose.ui.tooling.preview").get())
"implementation"(libs.findLibrary("androidx.lifecycle.runtimeCompose").get())
Expand Down
1 change: 1 addition & 0 deletions build-logic/src/main/kotlin/convention.feature.gradle.kts
Original file line number Diff line number Diff line change
Expand Up @@ -11,5 +11,6 @@ dependencies{
implementation(project(":core:data"))
implementation(project(":core:domain"))
implementation(project(":core:designsystem"))
implementation(project(":core:ui"))
testImplementation(project(":core:testing"))
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,41 @@
package com.withpeace.withpeace.core.designsystem.ui

import androidx.compose.foundation.BorderStroke
import androidx.compose.foundation.clickable
import androidx.compose.foundation.shape.RoundedCornerShape
import androidx.compose.material3.Card
import androidx.compose.material3.CardDefaults
import androidx.compose.material3.Text
import androidx.compose.runtime.Composable
import androidx.compose.ui.Modifier
import androidx.compose.ui.draw.clip
import androidx.compose.ui.tooling.preview.Preview
import androidx.compose.ui.unit.dp
import com.withpeace.withpeace.core.designsystem.theme.WithpeaceTheme

@Composable
fun WithpeaceCard(
Copy link
Contributor

Choose a reason for hiding this comment

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

어디에 쓰이는 카드인가요?!
캡쳐 해주시면 감사합니다

Copy link
Contributor Author

Choose a reason for hiding this comment

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

스크린샷 2024-03-19 오후 3 38 45
게시글 내용을 감싸는 테두리 라고 생각하시면 될 것 같습니다! 보통 저 테두리는 공통으로 쓰이기 때문에 designSystem으로 빼놨습니다

modifier: Modifier = Modifier,
content: @Composable () -> Unit,
) {
Card(
modifier = modifier,
shape = RoundedCornerShape(5.dp),
border = BorderStroke(width = 1.dp, color = WithpeaceTheme.colors.SystemGray2),
colors = CardDefaults.cardColors(
containerColor = WithpeaceTheme.colors.SystemWhite,
),
) {
content()
}
}

@Preview(showBackground = true)
@Composable
private fun WithpeaceCardPreview() {
WithpeaceTheme {
WithpeaceCard {
Text("haha")
}
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
package com.withpeace.withpeace.core.domain.model.date;

import java.time.LocalDateTime

data class Date(
val date: LocalDateTime,
) {
val durationFromNow: DurationFromNow
get() = DurationFromNow.from(date)
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,44 @@
package com.withpeace.withpeace.core.domain.model.date

import java.time.Duration
import java.time.LocalDateTime

sealed class DurationFromNow(
val value: Duration,
) {
data class LessThanOneMinute(val duration: Duration) : DurationFromNow(duration)
data class OneMinuteToOneHour(val duration: Duration) : DurationFromNow(duration)
data class OneHourToOneDay(val duration: Duration) : DurationFromNow(duration)
data class OneDayToSevenDay(val duration: Duration) : DurationFromNow(duration)
data class SevenDayToOneYear(val duration: Duration) : DurationFromNow(duration)
data class OverOneYear(val duration: Duration) : DurationFromNow(duration)

val seconds = value.seconds
val minutes = value.toMinutes()
val hours = value.toHours()
val days = value.toDays()
val years = value.toDays() / DAYS_FOR_YEAR

companion object {
fun from(date: LocalDateTime): DurationFromNow {
val duration = Duration.between(date, LocalDateTime.now())
return when {
duration.isLessThanOneMinute() -> LessThanOneMinute(duration)
duration.isLessThanOneHour() -> OneMinuteToOneHour(duration)
duration.isLessThanOneDay() -> OneHourToOneDay(duration)
duration.isLessThanWeekDays() -> OneDayToSevenDay(duration)
duration.isLessOneYear() -> SevenDayToOneYear(duration)
else -> OverOneYear(duration)
}
}

private fun Duration.isLessThanOneMinute() = toMinutes() < 1
private fun Duration.isLessThanOneHour() = toHours() < 1
private fun Duration.isLessThanOneDay() = toDays() < 1
private fun Duration.isLessThanWeekDays() = toDays() < DAYS_FOR_WEEK
private fun Duration.isLessOneYear() = toDays() < DAYS_FOR_YEAR

private const val DAYS_FOR_YEAR = 365
private const val DAYS_FOR_WEEK = 7
}
}
Original file line number Diff line number Diff line change
@@ -1,5 +1,12 @@
package com.withpeace.withpeace.core.domain.model.post

import com.withpeace.withpeace.core.domain.model.date.Date

data class Post(
val postId: Long,
val title: String,
val content: String,
val postTopic: PostTopic,
val createDate: Date,
val postImageUrl: String?,
)
Original file line number Diff line number Diff line change
@@ -1,5 +1,9 @@
package com.withpeace.withpeace.core.domain.model.post

enum class PostTopic {
FREEDOM, INFORMATION, QUESTION, LIVING, HOBBY, ECONOMY
FREEDOM, INFORMATION, QUESTION, LIVING, HOBBY, ECONOMY;

companion object {
fun findIndex(postTopic: PostTopic) = entries.indexOf(postTopic)
}
}
File renamed without changes.
13 changes: 13 additions & 0 deletions core/ui/build.gradle.kts
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
plugins {
id("com.android.library")
id("convention.android.base")
id("convention.android.compose")
}

android {
namespace = "com.withpeace.withpeace.core.ui"
}

dependencies {
implementation(project(":core:domain"))
}
File renamed without changes.
File renamed without changes.
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
package com.withpeace.withpeace.feature.post
package com.withpeace.withpeace.core.ui

import androidx.test.platform.app.InstrumentationRegistry
import androidx.test.ext.junit.runners.AndroidJUnit4
Expand All @@ -19,6 +19,6 @@ class ExampleInstrumentedTest {
fun useAppContext() {
// Context of the app under test.
val appContext = InstrumentationRegistry.getInstrumentation().targetContext
assertEquals("com.withpeace.withpeace.feature.post.test", appContext.packageName)
assertEquals("com.withpeace.withpeace.core.ui.test", appContext.packageName)
}
}
}
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android">

</manifest>
</manifest>
Original file line number Diff line number Diff line change
@@ -0,0 +1,37 @@
package com.withpeace.withpeace.core.ui

import android.content.Context
import com.withpeace.withpeace.core.domain.model.date.Date
import com.withpeace.withpeace.core.domain.model.date.DurationFromNow
import java.time.format.DateTimeFormatter

fun Date.toRelativeString(context: Context): String {
return when (durationFromNow) {
is DurationFromNow.LessThanOneMinute -> {
context.getString(
R.string.second_format,
durationFromNow.seconds,
)
}

is DurationFromNow.OneMinuteToOneHour -> context.getString(
R.string.minute_format,
durationFromNow.minutes,
)
is DurationFromNow.OneHourToOneDay -> context.getString(
R.string.hour_format,
durationFromNow.hours,
)
is DurationFromNow.OneDayToSevenDay -> context.getString(
R.string.day_format,
durationFromNow.days,
)
is DurationFromNow.SevenDayToOneYear -> date.format(DateTimeFormatter.ofPattern(DATE_FORMAT))
is DurationFromNow.OverOneYear -> context.getString(
R.string.years_format,
durationFromNow.years,
)
}
}

private const val DATE_FORMAT = "MM월 DD일"
Original file line number Diff line number Diff line change
@@ -1,23 +1,23 @@
package com.withpeace.withpeace.feature.registerpost
package com.withpeace.withpeace.core.ui

import androidx.annotation.DrawableRes
import androidx.annotation.StringRes
import com.withpeace.withpeace.core.domain.model.post.PostTopic

enum class PosterTopicUiState(
enum class PostTopicUiState(
val topic: PostTopic,
@StringRes val textResId: Int,
@DrawableRes val iconResId: Int,
) {
FREE(PostTopic.FREEDOM, R.string.free, R.drawable.ic_cate_free),
INFORMATION(PostTopic.INFORMATION, R.string.information, R.drawable.ic_cate_info),
QUESTION(PostTopic.QUESTION, R.string.question, R.drawable.ic_cate_question),
LIFE(PostTopic.LIVING, R.string.life, R.drawable.ic_cate_living),
HOBBY(PostTopic.HOBBY, R.string.hobby, R.drawable.ic_cate_hobby),
ECONOMY(PostTopic.ECONOMY, R.string.economy, R.drawable.ic_cate_eco);
FREE(PostTopic.FREEDOM, R.string.free, R.drawable.ic_freedom),
INFORMATION(PostTopic.INFORMATION, R.string.information, R.drawable.ic_information),
QUESTION(PostTopic.QUESTION, R.string.question, R.drawable.ic_question),
LIFE(PostTopic.LIVING, R.string.life, R.drawable.ic_life),
HOBBY(PostTopic.HOBBY, R.string.hobby, R.drawable.ic_hobby),
ECONOMY(PostTopic.ECONOMY, R.string.economy, R.drawable.ic_economy);

companion object {
fun create(topic: PostTopic) = PosterTopicUiState.entries.find {
fun create(topic: PostTopic) = PostTopicUiState.entries.find {
it.topic == topic
} ?: throw IllegalStateException("UI에 정의하지 않은 Topic이 있어요!")
}
Expand Down
Loading
Loading