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

[Feature/#873] 오늘의 솝마디 콕찌르기 추천 기능 구현 #881

Merged
merged 39 commits into from
Oct 4, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
39 commits
Select commit Hold shift + click to select a range
1aa4880
feat: TodayFortuneBox 구현
s9hn Sep 25, 2024
427fcc1
feat: 오늘의 운세(TodayFortuneDashboard) UI 구현
s9hn Sep 25, 2024
1a75a66
feat: FortuneDetailRoute, FortuneDetailScreen 파일 분리
s9hn Sep 25, 2024
e265c4e
refactor: 패키지 네이밍 수정
s9hn Sep 25, 2024
3b483ac
feat: fortune 데이터레이어 구현
s9hn Sep 25, 2024
4241e3f
feat: fortune 도메인레이어 구현, internal 키워드 일괄 적용
s9hn Sep 25, 2024
533a29f
refactor: internal 키워드 삭제
s9hn Sep 25, 2024
f655b50
refactor: 함수 네이밍 수정
s9hn Sep 25, 2024
e26989c
feat: 레이어 의존성 추가
s9hn Sep 25, 2024
5950cec
refactor: 네트워크 path 수정
s9hn Sep 26, 2024
71001df
feat: 네트워크 통신 구현 및 state 적용
s9hn Sep 26, 2024
1e42c44
feat: 오늘의 솝마디 관련 유즈케이스 생성
s9hn Sep 26, 2024
625d11e
refactor: TodayFortuneBox 패딩값 추가
s9hn Sep 26, 2024
430b830
refactor: 타입 및 네이밍 수정
s9hn Sep 26, 2024
83c0641
refactor: internal 추가
s9hn Sep 26, 2024
8d86bcb
test: FortuneDetailScreenTest 구현
s9hn Sep 26, 2024
340c78e
Merge branch 'develop' of https://github.com/sopt-makers/sopt-android…
s9hn Sep 26, 2024
2ea3be9
feat: 콕 찌르기 대시보드 UI 구현
s9hn Sep 26, 2024
37e8027
feat: 콕 찌르기 유저 추천 API 연결
s9hn Sep 26, 2024
0bde946
refactor: UI State 수정 및 적용
s9hn Sep 26, 2024
2f9ffff
refactor: SimpleDataFormatter로 리팩터링
s9hn Sep 26, 2024
69a0acc
refactor: Timber 적용
s9hn Sep 26, 2024
8981910
build: 의존성 수정
s9hn Sep 26, 2024
a7c5b50
refactor: break strategy 적용
s9hn Sep 26, 2024
3c27c00
build: resolve merge conflict
s9hn Sep 27, 2024
c2ac6ed
refactor: 뷰모델 수정
s9hn Sep 27, 2024
138a332
build: resolve merge-conflict
s9hn Sep 30, 2024
48e6648
refactor: 프로필 사진 사이즈 수정
s9hn Oct 1, 2024
9a2ae03
refactor: 배경색 수정
s9hn Oct 1, 2024
20b6fac
feat: 프로필 클릭 시 플레이그라운드로 이동
s9hn Oct 1, 2024
6b37380
feat: 프로필 기본 이미지 구현
s9hn Oct 1, 2024
3f16042
refactor: 자잘한 개행 및 import
s9hn Oct 1, 2024
1291338
test: 기본 생성 파일 삭제
s9hn Oct 3, 2024
95bce58
refactor: 추천인 이름 글자수 제한 설정
s9hn Oct 4, 2024
f2dc7b7
test: 테스트 코드 수정
s9hn Oct 4, 2024
7e40410
refactor: uimodel의 isEmpty 프로퍼티 제거
s9hn Oct 4, 2024
b0cedac
Merge branch 'develop' of https://github.com/sopt-makers/sopt-android…
s9hn Oct 4, 2024
d0a3a68
refactor: vectorResource 적용
s9hn Oct 4, 2024
c5d74ca
build: spotless & baseline 적용
s9hn Oct 4, 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,028 changes: 1,010 additions & 1,018 deletions app/src/release/generated/baselineProfiles/baseline-prof.txt

Large diffs are not rendered by default.

2,028 changes: 1,010 additions & 1,018 deletions app/src/release/generated/baselineProfiles/startup-prof.txt

Large diffs are not rendered by default.

Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
/*
* MIT License
* Copyright 2024 SOPT - Shout Our Passion Together
* Copyright 2023-2024 SOPT - Shout Our Passion Together
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
Expand Down
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
/*
* MIT License
* Copyright 2024 SOPT - Shout Our Passion Together
* Copyright 2023-2024 SOPT - Shout Our Passion Together
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -24,7 +24,6 @@
*/
package org.sopt.official.data.poke.implementation

import javax.inject.Inject
import org.sopt.official.data.poke.dto.request.GetFriendListDetailRequest
import org.sopt.official.data.poke.dto.request.GetPokeMessageListRequest
import org.sopt.official.data.poke.dto.request.GetPokeNotificationListRequest
Expand All @@ -44,6 +43,7 @@ import org.sopt.official.domain.poke.entity.PokeUserResponse
import org.sopt.official.domain.poke.repository.PokeRepository
import org.sopt.official.domain.poke.type.PokeFriendType
import org.sopt.official.domain.poke.type.PokeMessageType
import javax.inject.Inject

class PokeRepositoryImpl @Inject constructor(
private val localDataSource: PokeLocalDataSource,
Expand All @@ -62,7 +62,7 @@ class PokeRepositoryImpl @Inject constructor(
return remoteDataSource.checkNewInPoke()
}

override suspend fun getOnboardingPokeUserList(randomType: String, size: Int): GetOnboardingPokeUserListResponse {
override suspend fun getOnboardingPokeUserList(randomType: String?, size: Int): GetOnboardingPokeUserListResponse {
return remoteDataSource.getOnboardingPokeUserList(randomType, size)
}

Expand Down Expand Up @@ -110,7 +110,7 @@ class PokeRepositoryImpl @Inject constructor(
)
}

override suspend fun pokeUser(userId: Int, isAnonymous: Boolean, message: String,): PokeUserResponse {
override suspend fun pokeUser(userId: Int, isAnonymous: Boolean, message: String): PokeUserResponse {
return remoteDataSource.pokeUser(
pokeUserRequest =
PokeUserRequest(
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -46,8 +46,8 @@ interface PokeService {

@GET("poke/random")
suspend fun getOnboardingPokeUserList(
@Query("randomType") randomType: String,
@Query("size") size: Int
@Query("randomType") randomType: String?,
@Query("size") size: Int,
): Response<PokeRandomUserListResult>

@GET("poke/to/me")
Expand All @@ -60,16 +60,16 @@ interface PokeService {
suspend fun getPokeFriendOfFriendList(): Response<List<PokeFriendOfFriendListResult>>

@GET("poke/to/me/list")
suspend fun getPokeNotificationList(@Query("page") page: Int,): Response<PokeNotificationResult>
suspend fun getPokeNotificationList(@Query("page") page: Int): Response<PokeNotificationResult>

@GET("poke/friend/list")
suspend fun getFriendListSummary(): Response<GetFriendListSummaryResult>

@GET("poke/friend/list")
suspend fun getFriendListDetail(@Query("type") type: String, @Query("page") page: Int,): Response<GetFriendListDetailResult>
suspend fun getFriendListDetail(@Query("type") type: String, @Query("page") page: Int): Response<GetFriendListDetailResult>

@GET("poke/message")
suspend fun getPokeMessageList(@Query("messageType") messageType: String,): Response<GetPokeMessageListResult>
suspend fun getPokeMessageList(@Query("messageType") messageType: String): Response<GetPokeMessageListResult>

@PUT("poke/{userId}")
suspend fun pokeUser(@Path("userId") userId: Int, @Body pokeMessageRequest: PokeMessageRequest): Response<PokeUserResult>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -24,7 +24,6 @@
*/
package org.sopt.official.data.poke.source.remote

import javax.inject.Inject
import org.sopt.official.data.poke.dto.request.GetFriendListDetailRequest
import org.sopt.official.data.poke.dto.request.GetPokeMessageListRequest
import org.sopt.official.data.poke.dto.request.GetPokeNotificationListRequest
Expand All @@ -41,6 +40,7 @@ import org.sopt.official.domain.poke.entity.GetPokeMeResponse
import org.sopt.official.domain.poke.entity.GetPokeMessageListResponse
import org.sopt.official.domain.poke.entity.GetPokeNotificationListResponse
import org.sopt.official.domain.poke.entity.PokeUserResponse
import javax.inject.Inject

class PokeRemoteDataSource @Inject constructor(
private val service: PokeService,
Expand All @@ -54,7 +54,7 @@ class PokeRemoteDataSource @Inject constructor(
}
}

suspend fun getOnboardingPokeUserList(randomType: String, size: Int): GetOnboardingPokeUserListResponse {
suspend fun getOnboardingPokeUserList(randomType: String?, size: Int): GetOnboardingPokeUserListResponse {
val response = service.getOnboardingPokeUserList(randomType, size)
return GetOnboardingPokeUserListResponse().apply {
statusCode = response.code().toString()
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -41,17 +41,17 @@ interface PokeRepository {
suspend fun checkNewInPokeOnboarding(): Boolean
suspend fun updateNewInPokeOnboarding()
suspend fun checkNewInPoke(): CheckNewInPokeResponse
suspend fun getOnboardingPokeUserList(randomType: String, size: Int): GetOnboardingPokeUserListResponse
suspend fun getOnboardingPokeUserList(randomType: String? = null, size: Int): GetOnboardingPokeUserListResponse
suspend fun getPokeMe(): GetPokeMeResponse
suspend fun getPokeFriend(): GetPokeFriendResponse
suspend fun getPokeFriendOfFriendList(): GetPokeFriendOfFriendListResponse
suspend fun getPokeNotificationList(page: Int): GetPokeNotificationListResponse

suspend fun getFriendListSummary(): GetFriendListSummaryResponse

suspend fun getFriendListDetail(type: PokeFriendType, page: Int,): GetFriendListDetailResponse
suspend fun getFriendListDetail(type: PokeFriendType, page: Int): GetFriendListDetailResponse

suspend fun getPokeMessageList(messageType: PokeMessageType,): GetPokeMessageListResponse
suspend fun getPokeMessageList(messageType: PokeMessageType): GetPokeMessageListResponse

suspend fun pokeUser(userId: Int, isAnonymous: Boolean, message: String,): PokeUserResponse
suspend fun pokeUser(userId: Int, isAnonymous: Boolean, message: String): PokeUserResponse
}
Original file line number Diff line number Diff line change
Expand Up @@ -24,11 +24,11 @@
*/
package org.sopt.official.domain.poke.usecase

import javax.inject.Inject
import org.sopt.official.domain.poke.entity.ApiResult
import org.sopt.official.domain.poke.entity.PokeRandomUserList
import org.sopt.official.domain.poke.entity.apiResult
import org.sopt.official.domain.poke.repository.PokeRepository
import javax.inject.Inject

class GetOnboardingPokeUserListUseCase @Inject constructor(
private val repository: PokeRepository,
Expand Down
1 change: 1 addition & 0 deletions feature/fortune/build.gradle.kts
Original file line number Diff line number Diff line change
Expand Up @@ -35,6 +35,7 @@ android {
dependencies {
// domain
implementation(projects.domain.fortune)
implementation(projects.domain.poke)

// core
implementation(projects.core.common)
Expand Down

This file was deleted.

Original file line number Diff line number Diff line change
Expand Up @@ -35,7 +35,9 @@ import org.junit.Rule
import org.junit.Test
import org.sopt.official.designsystem.SoptTheme
import org.sopt.official.feature.fortune.feature.fortuneDetail.FortuneDetailScreen
import org.sopt.official.feature.fortune.feature.fortuneDetail.model.FortuneDetailUiState
import org.sopt.official.feature.fortune.feature.fortuneDetail.model.FortuneDetailUiState.Success
import org.sopt.official.feature.fortune.feature.fortuneDetail.model.FortuneDetailUiState.Success.TodaySentence
import org.sopt.official.feature.fortune.feature.fortuneDetail.model.FortuneDetailUiState.Success.UserInfo

internal class FortuneDetailScreenTest {

Expand All @@ -50,17 +52,27 @@ internal class FortuneDetailScreenTest {
val content = "안녕하세요안녕하세요안녕하세요안녕하세요안녕하세요"

// when:

composeRule.setContent {
SoptTheme {
FortuneDetailScreen(
paddingValue = PaddingValues(),
date = date,
onFortuneAmuletClick = { },
uiState = FortuneDetailUiState.TodaySentence(
userName = name,
content = content,
)
onPokeClick = { },
onProfileClick = { },
uiState = Success(
todaySentence = TodaySentence(
userName = name,
content = content,
),
userInfo = UserInfo(
userId = 0L,
profile = "",
userName = "동민",
generation = 111,
part = "기획 파트",
)
),
)
}
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -24,9 +24,12 @@
*/
package org.sopt.official.feature.fortune.feature.fortuneDetail

import android.content.Intent
import android.net.Uri
import androidx.compose.foundation.layout.PaddingValues
import androidx.compose.runtime.Composable
import androidx.compose.runtime.getValue
import androidx.compose.ui.platform.LocalContext
import androidx.hilt.navigation.compose.hiltViewModel
import androidx.lifecycle.compose.collectAsStateWithLifecycle

Expand All @@ -37,12 +40,19 @@ internal fun FortuneDetailRoute(
onFortuneAmuletClick: () -> Unit,
viewModel: FortuneDetailViewModel = hiltViewModel(),
) {
val context = LocalContext.current
val uiState by viewModel.uiState.collectAsStateWithLifecycle()

FortuneDetailScreen(
paddingValue = paddingValue,
date = date,
onFortuneAmuletClick = onFortuneAmuletClick,
onPokeClick = {},
onProfileClick = { userId ->
context.startActivity(
Intent(Intent.ACTION_VIEW, Uri.parse("https://playground.sopt.org/members/${userId}"))
)
},
Comment on lines +51 to +55
Copy link
Member

Choose a reason for hiding this comment

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

외부 뷰로 빠지는건가? 우리 WebViewActivity 활용하는 스펙은 아닌거?

Copy link
Contributor Author

Choose a reason for hiding this comment

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

넵 그냥 외부 뷰로 이동한다고 하더라구욥

Copy link
Member

Choose a reason for hiding this comment

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

기존에 콕찌르기에서 저렇게 되어있어서 세훈햄한테 외부 뷰로 빠진다고 이야기했었습니다!
근데 음... 협의만 된다면 WebVIewActivity 쓰는것도 좋을 것 같네용

uiState = uiState,
)
}
Original file line number Diff line number Diff line change
Expand Up @@ -36,31 +36,46 @@ import androidx.compose.ui.Modifier
import androidx.compose.ui.tooling.preview.Preview
import androidx.compose.ui.unit.dp
import org.sopt.official.designsystem.SoptTheme
import org.sopt.official.feature.fortune.feature.fortuneDetail.component.PokeRecommendationDashboard
import org.sopt.official.feature.fortune.feature.fortuneDetail.component.TodayFortuneDashboard
import org.sopt.official.feature.fortune.feature.fortuneDetail.model.FortuneDetailUiState
import org.sopt.official.feature.fortune.feature.fortuneDetail.model.FortuneDetailUiState.Error
import org.sopt.official.feature.fortune.feature.fortuneDetail.model.FortuneDetailUiState.Loading
import org.sopt.official.feature.fortune.feature.fortuneDetail.model.FortuneDetailUiState.TodaySentence
import org.sopt.official.feature.fortune.feature.fortuneDetail.model.FortuneDetailUiState.Success
import org.sopt.official.feature.fortune.feature.fortuneDetail.model.FortuneDetailUiState.Success.TodaySentence
import org.sopt.official.feature.fortune.feature.fortuneDetail.model.FortuneDetailUiState.Success.UserInfo
import timber.log.Timber

@Composable
internal fun FortuneDetailScreen(
paddingValue: PaddingValues,
date: String,
onFortuneAmuletClick: () -> Unit,
onPokeClick: (userId: Long) -> Unit,
onProfileClick: (userId: Long) -> Unit,
modifier: Modifier = Modifier,
uiState: FortuneDetailUiState = Loading,
) {
Column(
horizontalAlignment = Alignment.CenterHorizontally,
modifier = modifier.fillMaxSize().padding(paddingValues = paddingValue),
modifier = modifier
.fillMaxSize()
.padding(paddingValues = paddingValue),
) {
Spacer(modifier = Modifier.height(height = 16.dp))
when (uiState) {
is TodaySentence -> {
is Success -> {
TodayFortuneDashboard(
date = date,
todaySentence = uiState.message,
todaySentence = uiState.todaySentence.message,
)
Spacer(modifier = Modifier.height(height = 20.dp))
PokeRecommendationDashboard(
profile = uiState.userInfo.profile,
name = uiState.userInfo.userName,
userDescription = uiState.userInfo.userDescription,
onPokeClick = { onPokeClick(uiState.userInfo.userId) },
onProfileClick = { onProfileClick(uiState.userInfo.userId) }
Comment on lines +77 to +78
Copy link
Member

Choose a reason for hiding this comment

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

onPokeClick 함수에서 userId 값을 넘겨준다면 아래처럼 간단하게 쓸 수 있어요.
아래처럼 작성한다면 코드가 간단해지고, 캡쳐되기 때문에 약간의 성능 향상이 있지만, id라는 값을 넘겨주는 것 때문에 너무 강한 결합이 생기지 않을까?? 라는 고민을 요즘 하고있습니다. 혹시 어떻게 생각하시나용???

Suggested change
onPokeClick = { onPokeClick(uiState.userInfo.userId) },
onProfileClick = { onProfileClick(uiState.userInfo.userId) }
onPokeClick = onPokeClick,
onProfileClick = onProfileClick

Copy link
Contributor Author

Choose a reason for hiding this comment

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

오호~ 킹치만 호이스팅된 onXXXClick 함수들은 인자로 아무것도 넘겨주지 않아서 아래코드처럼 쓸 수 없습니당!
본 함수 람다에서 무엇을 넘겨줘야할지 구현해줘야해서 위처럼 작성했습니다

실제 onPokeClick, onProfileClick 등을 생성자로 받고있는 하위 컴포넌트들은 클릭 시 id를 넘겨줘야함!과 같은 구체적인 구현사항에 의존하지 않고, 호이스팅 된 상위 컴포넌트에서 위처럼 람다를 구현해서 상위로 전달해줍니다.
람다와 id가 강한결합.. 사실 그렇게 와닿지 않아서 잘 이해가 가진 않아요! 결국 필연적인 로직이라 생각하거든요 :)

Copy link
Member

Choose a reason for hiding this comment

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

아 코드를 제가 잘못 이해했었네요.
PokeRecommendationDashboard에 userInfo의 id도 같이 넘겨주고 있는 것으로 착각했습니다!

)
}

Expand All @@ -80,10 +95,21 @@ private fun FortuneDetailScreenPreview() {
paddingValue = PaddingValues(vertical = 16.dp),
date = "2024-09-09",
onFortuneAmuletClick = {},
uiState = TodaySentence(
userName = "누누",
content = "오늘 하루종일 기분 좋을 것 같은 날이네요.",
uiState = Success(
todaySentence = TodaySentence(
userName = "이현우",
content = "사과해요나한테사과해요나한테사과해요나한테"
),
userInfo = UserInfo(
userId = 0L,
profile = "",
userName = "동민",
generation = 111,
part = "기획 파트"
)
),
onPokeClick = { },
onProfileClick = { },
)
}
}
Loading