diff --git a/.github/workflows/android_cd.yml b/.github/workflows/android_cd.yml index 2fb81c23..a810e146 100644 --- a/.github/workflows/android_cd.yml +++ b/.github/workflows/android_cd.yml @@ -68,6 +68,10 @@ jobs: - name: Debug Local Properties run: cat local.properties + - name: Extract Version Name + run: echo "##[set-output name=version;]v$(echo '${{ github.event.pull_request.title }}' | grep -oP 'release v\K[0-9]+\.[0-9]+\.[0-9]+')" + id: extract_version + # 8. Release APK Build - name: Build Release APK run: ./gradlew assembleRelease --stacktrace @@ -86,14 +90,6 @@ jobs: name: release-apk path: app/build/outputs/apk/release/app-release.apk - # 버전 정보 추출 - - name: Get App Version - id: get_version - run: | - version=$(grep -oP 'versionName\s*"\K[^"]+' app/build.gradle) - echo "VERSION=$version" >> $GITHUB_ENV - echo "Extracted version: $version" - # 11. Firebase App Distribution - name: Upload to Firebase App Distribution uses: wzieba/Firebase-Distribution-Github-Action@v1 @@ -102,7 +98,7 @@ jobs: serviceCredentialsFileContent: ${{ secrets.CREDENTIAL_FILE_CONTENT }} groups: seungwon file: app/build/outputs/apk/release/app-release.apk - releaseNotes: "새로운 버전 v${{ env.VERSION }} 출시" + releaseNotes: "새로운 버전 v${{ steps.extract_version.outputs.version }} 출시" # 12. Notify Discord - name: Notify Discord @@ -111,5 +107,5 @@ jobs: run: | curl -H "Content-Type: application/json" \ -X POST \ - -d "{\"content\": \"🚀 새로운 버전 v${{ env.VERSION }}이 Firebase App Distribution에 업로드되었습니다!\nAPK 다운로드: https://appdistribution.firebase.google.com\"}" \ + -d "{\"content\": \"🚀 새로운 버전 v${{ steps.extract_version.outputs.version }}이 Firebase App Distribution에 업로드되었습니다!\nAPK 다운로드: https://appdistribution.firebase.google.com\"}" \ $DISCORD_WEBHOOK_URL diff --git a/app/build.gradle.kts b/app/build.gradle.kts index b2d33018..8133acd7 100644 --- a/app/build.gradle.kts +++ b/app/build.gradle.kts @@ -16,7 +16,11 @@ val nativeAppKey = localProperties.getProperty("kakao_NATIVE_APP_KEY_MANIFEST")? android { signingConfigs { - create("release") { + getByName("debug") { + keyAlias = localProperties["SIGNED_KEY_ALIAS"] as String? + keyPassword = localProperties["SIGNED_KEY_PASSWORD"] as String? + storeFile = localProperties["SIGNED_STORE_FILE"]?.let { file(it) } + storePassword = localProperties["SIGNED_STORE_PASSWORD"] as String? } } namespace = "com.toyou.toyouandroid" @@ -27,7 +31,7 @@ android { minSdk = 28 targetSdk = 34 versionCode = 11 - versionName = "1.0.10" + versionName = "1.1.0" testInstrumentationRunner = "androidx.test.runner.AndroidJUnitRunner" diff --git a/app/release/app-release.aab b/app/release/app-release.aab deleted file mode 100644 index 9496f603..00000000 Binary files a/app/release/app-release.aab and /dev/null differ diff --git a/app/src/main/java/com/toyou/toyouandroid/data/UserDao.kt b/app/src/main/java/com/toyou/toyouandroid/data/UserDao.kt deleted file mode 100644 index 33e7138a..00000000 --- a/app/src/main/java/com/toyou/toyouandroid/data/UserDao.kt +++ /dev/null @@ -1,21 +0,0 @@ -package com.toyou.toyouandroid.data - -import androidx.room.Dao -import androidx.room.Insert -import androidx.room.Query -import androidx.room.Update - -@Dao -interface UserDao { - @Insert - suspend fun insert(userEntity: UserEntity) - - @Query("SELECT * FROM UserEntity") - suspend fun getAll(): List - - @Query("DELETE FROM UserEntity") - suspend fun deleteAll() - - @Update - suspend fun update(user: UserEntity) -} \ No newline at end of file diff --git a/app/src/main/java/com/toyou/toyouandroid/data/UserDatabase.kt b/app/src/main/java/com/toyou/toyouandroid/data/UserDatabase.kt deleted file mode 100644 index 2df7d173..00000000 --- a/app/src/main/java/com/toyou/toyouandroid/data/UserDatabase.kt +++ /dev/null @@ -1,28 +0,0 @@ -package com.toyou.toyouandroid.data - -import android.content.Context -import androidx.room.Database -import androidx.room.Room -import androidx.room.RoomDatabase - -@Database(entities = [UserEntity::class], version = 1) -abstract class UserDatabase : RoomDatabase() { - abstract fun dao() : UserDao - - companion object { - @Volatile - private var Instance : UserDatabase? = null - - fun getDatabase(context: Context) : UserDatabase{ - return Instance ?: synchronized(this) { - val instance = Room.databaseBuilder( - context.applicationContext, - UserDatabase::class.java, - "user-database" - ).build() - Instance = instance - instance - } - } - } -} \ No newline at end of file diff --git a/app/src/main/java/com/toyou/toyouandroid/data/UserEntity.kt b/app/src/main/java/com/toyou/toyouandroid/data/UserEntity.kt deleted file mode 100644 index 49ff5ab1..00000000 --- a/app/src/main/java/com/toyou/toyouandroid/data/UserEntity.kt +++ /dev/null @@ -1,11 +0,0 @@ -package com.toyou.toyouandroid.data - -import androidx.room.Entity -import androidx.room.PrimaryKey - -@Entity -data class UserEntity( - @PrimaryKey(autoGenerate = true) val id: Int = 0, - val emotion: String?, - val cardId: Int? -) diff --git a/app/src/main/java/com/toyou/toyouandroid/data/home/dto/response/YesterdayCardResponse.kt b/app/src/main/java/com/toyou/toyouandroid/data/home/dto/response/YesterdayCardResponse.kt new file mode 100644 index 00000000..47524270 --- /dev/null +++ b/app/src/main/java/com/toyou/toyouandroid/data/home/dto/response/YesterdayCardResponse.kt @@ -0,0 +1,29 @@ +package com.toyou.toyouandroid.data.home.dto.response + +import com.google.gson.annotations.SerializedName + +data class YesterdayCardResponse( + @SerializedName("cards") val yesterday: List +) + +data class YesterdayCard( + @SerializedName("cardId") val cardId: Long, + @SerializedName("cardContent") val cardContent: YesterdayCardContent +) + +data class YesterdayCardContent( + @SerializedName("date") val date: String, + @SerializedName("receiver") val receiver: String, + @SerializedName("emotion") val emotion: String, + @SerializedName("exposure") val exposure: Boolean, + @SerializedName("questionList") val questionList: List +) + +data class YesterdayCardQuestion( + @SerializedName("questionId") val id: Long, + @SerializedName("content") val content: String, + @SerializedName("questionType") val type: String, + @SerializedName("questioner") val questioner: String, + @SerializedName("answer") val answer: String, + @SerializedName("answerOption") val options: List? +) diff --git a/app/src/main/java/com/toyou/toyouandroid/data/home/service/HomeService.kt b/app/src/main/java/com/toyou/toyouandroid/data/home/service/HomeService.kt index cbcd5510..d9c5be29 100644 --- a/app/src/main/java/com/toyou/toyouandroid/data/home/service/HomeService.kt +++ b/app/src/main/java/com/toyou/toyouandroid/data/home/service/HomeService.kt @@ -1,6 +1,7 @@ package com.toyou.toyouandroid.data.home.service import com.toyou.toyouandroid.data.home.dto.response.CardDetail +import com.toyou.toyouandroid.data.home.dto.response.YesterdayCardResponse import com.toyou.toyouandroid.network.BaseResponse import retrofit2.http.GET import retrofit2.http.Header @@ -12,4 +13,8 @@ interface HomeService { suspend fun getCardDetail( @Path("cardId") card : Long ) : BaseResponse + + @GET("/diarycards/yesterday") + suspend fun getCardYesterday( + ) : BaseResponse } \ No newline at end of file diff --git a/app/src/main/java/com/toyou/toyouandroid/domain/home/repository/HomeRepository.kt b/app/src/main/java/com/toyou/toyouandroid/domain/home/repository/HomeRepository.kt index ac8c00b7..bb2367a3 100644 --- a/app/src/main/java/com/toyou/toyouandroid/domain/home/repository/HomeRepository.kt +++ b/app/src/main/java/com/toyou/toyouandroid/domain/home/repository/HomeRepository.kt @@ -1,10 +1,14 @@ package com.toyou.toyouandroid.domain.home.repository +import com.toyou.toyouandroid.data.home.dto.response.YesterdayCardResponse import com.toyou.toyouandroid.data.home.service.HomeService import com.toyou.toyouandroid.network.AuthNetworkModule +import com.toyou.toyouandroid.network.BaseResponse class HomeRepository { private val client = AuthNetworkModule.getClient().create(HomeService::class.java) suspend fun getCardDetail(id : Long)=client.getCardDetail(id) + + suspend fun getYesterdayCard() = client.getCardYesterday() } \ No newline at end of file diff --git a/app/src/main/java/com/toyou/toyouandroid/model/YesterdayType.kt b/app/src/main/java/com/toyou/toyouandroid/model/YesterdayType.kt new file mode 100644 index 00000000..219c88a3 --- /dev/null +++ b/app/src/main/java/com/toyou/toyouandroid/model/YesterdayType.kt @@ -0,0 +1,6 @@ +package com.toyou.toyouandroid.model; + +const val Ytype1 = "LONG_ANSWER" +const val Ytype2 = "SHORT_ANSWER" +const val Ytype3 = "OPTIONAL" +const val Ytype4 = 3 diff --git a/app/src/main/java/com/toyou/toyouandroid/presentation/fragment/emotionstamp/HomeOptionFragment.kt b/app/src/main/java/com/toyou/toyouandroid/presentation/fragment/emotionstamp/HomeOptionFragment.kt index 08b49e7d..88303f70 100644 --- a/app/src/main/java/com/toyou/toyouandroid/presentation/fragment/emotionstamp/HomeOptionFragment.kt +++ b/app/src/main/java/com/toyou/toyouandroid/presentation/fragment/emotionstamp/HomeOptionFragment.kt @@ -19,6 +19,7 @@ import com.toyou.toyouandroid.data.emotion.dto.EmotionRequest import com.toyou.toyouandroid.data.onboarding.service.AuthService import com.toyou.toyouandroid.data.social.service.SocialService import com.toyou.toyouandroid.domain.create.repository.CreateRepository +import com.toyou.toyouandroid.domain.home.repository.HomeRepository import com.toyou.toyouandroid.network.AuthNetworkModule import com.toyou.toyouandroid.network.NetworkModule import com.toyou.toyouandroid.presentation.fragment.notice.NoticeDialog @@ -57,18 +58,19 @@ class HomeOptionFragment : Fragment() { val createService = AuthNetworkModule.getClient().create(CreateService::class.java) val createRepository = CreateRepository(createService) + val homeRepository = HomeRepository() homeOptionViewModel = ViewModelProvider( this, HomeViewModelFactory( - tokenManager + tokenManager, homeRepository ) )[HomeOptionViewModel::class.java] homeViewModel = ViewModelProvider( this, HomeViewModelFactory( - tokenManager + tokenManager, homeRepository ) )[HomeViewModel::class.java] diff --git a/app/src/main/java/com/toyou/toyouandroid/presentation/fragment/home/HomeFragment.kt b/app/src/main/java/com/toyou/toyouandroid/presentation/fragment/home/HomeFragment.kt index b11e905f..aa294277 100644 --- a/app/src/main/java/com/toyou/toyouandroid/presentation/fragment/home/HomeFragment.kt +++ b/app/src/main/java/com/toyou/toyouandroid/presentation/fragment/home/HomeFragment.kt @@ -16,11 +16,10 @@ import androidx.recyclerview.widget.GridLayoutManager import com.google.android.material.bottomsheet.BottomSheetBehavior import com.toyou.toyouHoandroid.data.create.service.CreateService import com.toyou.toyouandroid.R -import com.toyou.toyouandroid.data.UserDatabase import com.toyou.toyouandroid.databinding.FragmentHomeBinding import com.toyou.toyouandroid.network.AuthNetworkModule import com.toyou.toyouandroid.presentation.base.MainActivity -import com.toyou.toyouandroid.data.emotion.dto.DiaryCard +import com.toyou.toyouandroid.data.home.dto.response.YesterdayCard import com.toyou.toyouandroid.presentation.fragment.home.adapter.HomeBottomSheetAdapter import com.toyou.toyouandroid.presentation.fragment.notice.NoticeViewModel import com.toyou.toyouandroid.domain.notice.NoticeRepository @@ -28,6 +27,7 @@ import com.toyou.toyouandroid.data.notice.service.NoticeService import com.toyou.toyouandroid.data.onboarding.service.AuthService import com.toyou.toyouandroid.data.record.service.RecordService import com.toyou.toyouandroid.domain.create.repository.CreateRepository +import com.toyou.toyouandroid.domain.home.repository.HomeRepository import com.toyou.toyouandroid.domain.record.RecordRepository import com.toyou.toyouandroid.network.NetworkModule import com.toyou.toyouandroid.presentation.viewmodel.NoticeViewModelFactory @@ -54,7 +54,6 @@ class HomeFragment : Fragment() { private lateinit var bottomSheetBehavior: BottomSheetBehavior private lateinit var userViewModel: UserViewModel - private lateinit var database: UserDatabase private lateinit var cardViewModel: CardViewModel private lateinit var listener: HomeBottomSheetClickListener @@ -79,6 +78,7 @@ class HomeFragment : Fragment() { val recordRepository = RecordRepository(recordService) val createService = AuthNetworkModule.getClient().create(CreateService::class.java) val createRepository = CreateRepository(createService) + val homeRepository = HomeRepository() noticeViewModel = ViewModelProvider( @@ -88,7 +88,7 @@ class HomeFragment : Fragment() { viewModel = ViewModelProvider( this, - HomeViewModelFactory(tokenManager) + HomeViewModelFactory(tokenManager, homeRepository) )[HomeViewModel::class.java] binding.lifecycleOwner = viewLifecycleOwner @@ -121,7 +121,6 @@ class HomeFragment : Fragment() { override fun onDiaryCardClick(cardId: Int?) { Timber.tag("HomeFragment").d("$cardId") cardId?.let { - cardInfoViewModel.getCardDetail(cardId.toLong()) val bundle = Bundle().apply { putInt("cardId", it) } @@ -140,7 +139,10 @@ class HomeFragment : Fragment() { (requireActivity() as MainActivity).hideBottomNavigation(false) - database = UserDatabase.getDatabase(requireContext()) + + //일기카드 조회 + viewModel.getYesterdayCard() + // 질문 개수에 따른 우체통 이미지 변경 userViewModel.cardNum.observe(viewLifecycleOwner) { cardNum -> @@ -175,9 +177,6 @@ class HomeFragment : Fragment() { binding.homeBottomsheetPseudo.visibility = View.VISIBLE binding.homeBottomSheetRv.visibility = View.GONE - // 작일 친구 일기 카드 자동 조회 -// viewModel.loadYesterdayDiaryCards() - // 바텀 시트 터치 이벤트 처리 binding.homeBottomSheet.apply { setOnTouchListener { v, event -> @@ -201,9 +200,14 @@ class HomeFragment : Fragment() { } // 홈 화면 바텀 시트 설정 - viewModel.diaryCards.observe(viewLifecycleOwner) { diaryCards -> - if (diaryCards != null) { - setupRecyclerView(diaryCards) + viewModel.yesterdayCards.observe(viewLifecycleOwner) { yesterdayCards -> + if (yesterdayCards.isNotEmpty()) { + binding.homeBottomsheetPseudo.visibility = View.GONE + binding.homeBottomSheetRv.visibility = View.VISIBLE + setupRecyclerView(yesterdayCards) + } else { + binding.homeBottomsheetPseudo.visibility = View.VISIBLE + binding.homeBottomSheetRv.visibility = View.GONE } } @@ -312,7 +316,7 @@ class HomeFragment : Fragment() { } } - private fun setupRecyclerView(items: List) { + private fun setupRecyclerView(items: List) { val adapter = HomeBottomSheetAdapter(items.toMutableList(), listener) binding.homeBottomSheetRv.layoutManager = GridLayoutManager(context, 2) diff --git a/app/src/main/java/com/toyou/toyouandroid/presentation/fragment/home/HomeViewModel.kt b/app/src/main/java/com/toyou/toyouandroid/presentation/fragment/home/HomeViewModel.kt index 5f34db21..b7e56c35 100644 --- a/app/src/main/java/com/toyou/toyouandroid/presentation/fragment/home/HomeViewModel.kt +++ b/app/src/main/java/com/toyou/toyouandroid/presentation/fragment/home/HomeViewModel.kt @@ -3,19 +3,25 @@ package com.toyou.toyouandroid.presentation.fragment.home import androidx.lifecycle.LiveData import androidx.lifecycle.MutableLiveData import androidx.lifecycle.ViewModel +import androidx.lifecycle.viewModelScope import com.toyou.toyouandroid.R import com.toyou.toyouandroid.network.AuthNetworkModule import com.toyou.toyouandroid.data.emotion.dto.DiaryCard import com.toyou.toyouandroid.data.emotion.service.EmotionService import com.toyou.toyouandroid.data.emotion.dto.YesterdayFriendsResponse +import com.toyou.toyouandroid.data.home.dto.response.YesterdayCard +import com.toyou.toyouandroid.domain.home.repository.HomeRepository import com.toyou.toyouandroid.utils.TokenManager import com.toyou.toyouandroid.utils.calendar.getCurrentDate +import kotlinx.coroutines.launch import retrofit2.Call import retrofit2.Callback import retrofit2.Response import timber.log.Timber +import kotlin.math.log -class HomeViewModel(private val tokenManager: TokenManager) : ViewModel() { +class HomeViewModel(private val tokenManager: TokenManager, + private val repository: HomeRepository) : ViewModel() { private val _homeEmotion = MutableLiveData() val homeEmotion: LiveData get() = _homeEmotion @@ -38,6 +44,9 @@ class HomeViewModel(private val tokenManager: TokenManager) : ViewModel() { private val _isLoading = MutableLiveData() val isLoading: LiveData get() = _isLoading + private val _yesterdayCards = MutableLiveData>() + val yesterdayCards: LiveData> = _yesterdayCards + private val _isEmpty = MutableLiveData() val isEmpty: LiveData get() = _isEmpty @@ -60,54 +69,24 @@ class HomeViewModel(private val tokenManager: TokenManager) : ViewModel() { _homeDateBackground.value = R.color.g00 _homeBackground.value = R.drawable.background_white } - - fun loadYesterdayDiaryCards() { - _isLoading.value = true - - tokenManager.refreshToken( - onSuccess = { token -> - Timber.d("API 호출 - 사용된 Access Token: $token") - - apiService.getYesterdayFriendCard().enqueue(object : Callback { - override fun onResponse(call: Call, response: Response) { - if (response.isSuccessful) { - val diaryResponse = response.body() - Timber.d("API 응답 데이터: $diaryResponse") - - if (diaryResponse?.isSuccess == true) { - val cards = diaryResponse.result.yesterday - Timber.d("받아온 카드 목록: $cards") - - if (cards.isEmpty()) { - Timber.d("카드 목록이 비어 있습니다.") - _isEmpty.value = true - } else { - _diaryCards.value = cards - _isEmpty.value = false - } - } else { - Timber.e("API 호출 실패 - 응답이 성공하지 않음. 메시지: ${diaryResponse?.message}") - } - } else { - Timber.e("API 호출 실패 - 코드: ${response.code()}, 메시지: ${response.message()}") - } - - _isLoading.value = false - } - - override fun onFailure(call: Call, t: Throwable) { - Timber.e(t, "API 호출 실패 - 네트워크 오류") - _isLoading.value = false - _isEmpty.value = true // 실패 시 빈 상태로 간주 - } - }) - }, - onFailure = { - Timber.e("토큰 갱신 실패 - API 호출 중단") - _isLoading.value = false + fun getYesterdayCard() { + viewModelScope.launch { + try { + val response = repository.getYesterdayCard() + Timber.tag("HomeViewModel").d("yesterdayCards: ${response.result}") + if (response.isSuccess) { + _yesterdayCards.value = response.result.yesterday + Timber.tag("HomeViewModel").d("yesterdayCards: ${response.result.yesterday}") + } else { + tokenManager.refreshToken( + onSuccess = { getYesterdayCard() }, + onFailure = { Timber.tag("HomeViewModel").d("refresh error") } + ) + } + } catch (e: Exception) { + _yesterdayCards.value = emptyList() } - ) + } } - } diff --git a/app/src/main/java/com/toyou/toyouandroid/presentation/fragment/home/adapter/HomeBottomSheetAdapter.kt b/app/src/main/java/com/toyou/toyouandroid/presentation/fragment/home/adapter/HomeBottomSheetAdapter.kt index 143e9e71..174a1d0d 100644 --- a/app/src/main/java/com/toyou/toyouandroid/presentation/fragment/home/adapter/HomeBottomSheetAdapter.kt +++ b/app/src/main/java/com/toyou/toyouandroid/presentation/fragment/home/adapter/HomeBottomSheetAdapter.kt @@ -1,16 +1,17 @@ package com.toyou.toyouandroid.presentation.fragment.home.adapter +import android.graphics.Color import android.view.LayoutInflater import android.view.ViewGroup import androidx.recyclerview.widget.LinearLayoutManager import androidx.recyclerview.widget.RecyclerView +import com.toyou.toyouandroid.R import com.toyou.toyouandroid.databinding.ItemHomeBottomSheetBinding -import com.toyou.toyouandroid.data.emotion.dto.DiaryCard +import com.toyou.toyouandroid.data.home.dto.response.YesterdayCard import com.toyou.toyouandroid.presentation.fragment.home.HomeBottomSheetClickListener class HomeBottomSheetAdapter( - private val items: MutableList, -// private val cardDetails: List, + private val items: MutableList, private val listener: HomeBottomSheetClickListener ) : RecyclerView.Adapter() { @@ -22,7 +23,6 @@ class HomeBottomSheetAdapter( override fun onBindViewHolder(holder: ViewHolder, position: Int) { val item = items[position] -// val cardDetail = cardDetails.getOrNull(position) holder.bind(item) } @@ -32,18 +32,54 @@ class HomeBottomSheetAdapter( inner class ViewHolder(private val binding: ItemHomeBottomSheetBinding) : RecyclerView.ViewHolder(binding.root) { - fun bind(item: DiaryCard) { + fun bind(item: YesterdayCard) { val homeBottomSheetCardDetailAdapter = HomeBottomSheetCardDetailAdapter() + homeBottomSheetCardDetailAdapter.setCards(listOf(item)) binding.cardList.apply { layoutManager = LinearLayoutManager(binding.root.context, LinearLayoutManager.VERTICAL, false) adapter = homeBottomSheetCardDetailAdapter } + binding.itemHomeBottomSheet = item binding.itemHomeBottomSheet = item binding.homeBottomSheetItem.setOnClickListener { - listener.onDiaryCardClick(item.cardId) + listener.onDiaryCardClick(item.cardId.toInt()) + } + + binding.itemTitle.text = item.cardContent.receiver + + binding.itemDetail.text = item.cardContent.date + + binding.friendNickname.text = item.cardContent.receiver + + when(item.cardContent.emotion){ + "HAPPY" -> { + binding.itemImage.setImageResource(R.drawable.home_stamp_option_happy) + binding.cardView.setCardBackgroundColor(Color.parseColor("#FFF7F3E3")) + } + "EXCITED" -> { + binding.itemImage.setImageResource(R.drawable.home_stamp_option_exciting) + binding.cardView.setCardBackgroundColor(Color.parseColor("#FFE0EEF6")) + } + "NORMAL" -> { + binding.itemImage.setImageResource(R.drawable.home_stamp_option_normal) + binding.cardView.setCardBackgroundColor(Color.parseColor("#FFDFE1F1")) + } + "NERVOUS" -> { + binding.itemImage.setImageResource(R.drawable.home_stamp_option_anxiety) + binding.cardView.setCardBackgroundColor(Color.parseColor("#FFD6E4D9")) + } + "ANGRY" -> { + binding.itemImage.setImageResource(R.drawable.home_stamp_option_upset) + binding.cardView.setCardBackgroundColor(Color.parseColor("#FFF4DDDD")) + } + //임의로 감정이 null일때..일수는 없지만 + else -> { + binding.itemImage.setImageResource(R.drawable.home_stamp_option_upset) + binding.cardView.setCardBackgroundColor(Color.parseColor("#FFF4DDDD")) + } } binding.executePendingBindings() diff --git a/app/src/main/java/com/toyou/toyouandroid/presentation/fragment/home/adapter/HomeBottomSheetCardDetailAdapter.kt b/app/src/main/java/com/toyou/toyouandroid/presentation/fragment/home/adapter/HomeBottomSheetCardDetailAdapter.kt index 61c4b597..a5679d5b 100644 --- a/app/src/main/java/com/toyou/toyouandroid/presentation/fragment/home/adapter/HomeBottomSheetCardDetailAdapter.kt +++ b/app/src/main/java/com/toyou/toyouandroid/presentation/fragment/home/adapter/HomeBottomSheetCardDetailAdapter.kt @@ -6,65 +6,61 @@ import android.view.ViewGroup import android.widget.TextView import androidx.recyclerview.widget.RecyclerView import com.toyou.toyouandroid.R +import com.toyou.toyouandroid.data.home.dto.response.YesterdayCard +import com.toyou.toyouandroid.data.home.dto.response.YesterdayCardQuestion import com.toyou.toyouandroid.model.PreviewCardModel +import com.toyou.toyouandroid.model.Ytype1 import com.toyou.toyouandroid.model.type1 import com.toyou.toyouandroid.model.type2 import com.toyou.toyouandroid.model.type3 class HomeBottomSheetCardDetailAdapter : RecyclerView.Adapter() { - private var cardList : List = emptyList() - private lateinit var emotion: String + private var questionList: List = emptyList() + private var emotionMap: Map = emptyMap() // cardId -> emotion + private var questionToCardMap: Map = emptyMap() // questionId -> cardId - fun setCards(newCards: List) { - cardList = newCards - notifyDataSetChanged() - } + fun setCards(newCards: List) { + questionList = newCards.flatMap { it.cardContent.questionList } + + // 카드 ID별 감정을 저장 + emotionMap = newCards.associate { it.cardId to it.cardContent.emotion } + + // 질문 ID별 카드 ID를 저장 + questionToCardMap = newCards.flatMap { card -> + card.cardContent.questionList.map { it.id to card.cardId } + }.toMap() - fun setEmotion(emotion : String){ - this.emotion = emotion + notifyDataSetChanged() } override fun getItemViewType(position: Int): Int { - return cardList[position].type + return when (questionList[position].type) { + "LONG_ANSWER" -> 1 + "SHORT_ANSWER" -> 2 + "OPTIONAL" -> 3 + else -> 4 + } } - override fun onCreateViewHolder( - parent: ViewGroup, - viewType: Int - ): RecyclerView.ViewHolder { + override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): RecyclerView.ViewHolder { val view: View return when (viewType) { - type1 -> { + 1, 2 -> { view = LayoutInflater.from(parent.context).inflate( - R.layout.card_qa_list, - parent, - false + R.layout.item_yesterday_qa, parent, false ) MultiViewHolderPreview1(view) } - type2 -> { + 3 -> { view = LayoutInflater.from(parent.context).inflate( - R.layout.card_qa_list, - parent, - false - ) - MultiViewHolderPreview1(view) - } - type3 -> { - view = LayoutInflater.from(parent.context).inflate( - R.layout.item_answer_option_two, - parent, - false + R.layout.item_yesterday_option_two, parent, false ) MultiViewHolderPreview3(view) } - else -> { view = LayoutInflater.from(parent.context).inflate( - R.layout.item_answer_option_three, - parent, - false + R.layout.item_yesterday_option_three, parent, false ) MultiViewHolderPreview4(view) } @@ -72,28 +68,37 @@ class HomeBottomSheetCardDetailAdapter : RecyclerView.Adapter { - (holder as MultiViewHolderPreview1).bind(cardList[position]) - holder.setIsRecyclable(false) - } - type2 -> { - (holder as MultiViewHolderPreview1).bind(cardList[position]) - holder.setIsRecyclable(false) + val item = questionList[position] + + // 해당 질문이 속한 카드의 ID 찾기 + val cardId = questionToCardMap[item.id] ?: -1 + // 카드 ID를 통해 감정을 찾기 (없으면 기본값 "ANGRY") + val emotion = emotionMap[cardId] ?: "ANGRY" + + when (item.type) { + "LONG_ANSWER", "SHORT_ANSWER" -> { + (holder as MultiViewHolderPreview1).bind( + PreviewCardModel(item.content, item.answer, mapQuestionType(item.type), item.questioner, item.options, item.id) + ) } - type3 -> { - (holder as MultiViewHolderPreview3).bind(cardList[position]) - holder.setIsRecyclable(false) + "OPTIONAL" -> { + (holder as MultiViewHolderPreview3).bind( + PreviewCardModel(item.content, item.answer, mapQuestionType(item.type), item.questioner, item.options, item.id), + emotion + ) } - else -> { - (holder as MultiViewHolderPreview4).bind(cardList[position]) - holder.setIsRecyclable(false) + (holder as MultiViewHolderPreview4).bind( + PreviewCardModel(item.content, item.answer, mapQuestionType(item.type), item.questioner, item.options, item.id), + emotion + ) } } } - inner class MultiViewHolderPreview1(view: View) : RecyclerView.ViewHolder(view){ + override fun getItemCount(): Int = questionList.size + + inner class MultiViewHolderPreview1(view: View) : RecyclerView.ViewHolder(view) { private val question: TextView = view.findViewById(R.id.question) private val answer: TextView = view.findViewById(R.id.answer) @@ -103,92 +108,60 @@ class HomeBottomSheetCardDetailAdapter : RecyclerView.Adapter txtOption1.setBackgroundResource(R.drawable.selected_option_happy) - "EXCITED" -> txtOption1.setBackgroundResource(R.drawable.selected_option_excited) - "NORMAL" -> txtOption1.setBackgroundResource(R.drawable.selected_option_normal) - "NERVOUS" -> txtOption1.setBackgroundResource(R.drawable.selected_option_container) - "ANGRY" -> txtOption1.setBackgroundResource(R.drawable.selected_option_angry) - } - } else { - txtOption1.setBackgroundResource(R.drawable.search_container) - } - - if (item.answer == item.options[1]) { - when(emotion){ - "HAPPY" -> txtOption2.setBackgroundResource(R.drawable.selected_option_happy) - "EXCITED" -> txtOption2.setBackgroundResource(R.drawable.selected_option_excited) - "NORMAL" -> txtOption2.setBackgroundResource(R.drawable.selected_option_normal) - "NERVOUS" -> txtOption2.setBackgroundResource(R.drawable.selected_option_container) - "ANGRY" -> txtOption2.setBackgroundResource(R.drawable.selected_option_angry) - } - } else { - txtOption2.setBackgroundResource(R.drawable.search_container) - } + applyEmotionStyle(txtOption1, item.answer == item.options[0], emotion) + applyEmotionStyle(txtOption2, item.answer == item.options[1], emotion) } } - inner class MultiViewHolderPreview4(view: View) : RecyclerView.ViewHolder(view){ + inner class MultiViewHolderPreview4(view: View) : RecyclerView.ViewHolder(view) { private val question: TextView = view.findViewById(R.id.question) private val txtOption1: TextView = view.findViewById(R.id.choose_three_first_tv) private val txtOption2: TextView = view.findViewById(R.id.choose_three_second_tv) private val txtOption3: TextView = view.findViewById(R.id.choose_three_third_tv) - fun bind(item: PreviewCardModel) { + fun bind(item: PreviewCardModel, emotion: String) { question.text = item.question txtOption1.text = item.options!![0] txtOption2.text = item.options[1] txtOption3.text = item.options[2] - if (item.answer == item.options[0]) { - when(emotion){ - "HAPPY" -> txtOption1.setBackgroundResource(R.drawable.selected_option_happy) - "EXCITED" -> txtOption1.setBackgroundResource(R.drawable.selected_option_excited) - "NORMAL" -> txtOption1.setBackgroundResource(R.drawable.selected_option_normal) - "NERVOUS" -> txtOption1.setBackgroundResource(R.drawable.selected_option_container) - "ANGRY" -> txtOption1.setBackgroundResource(R.drawable.selected_option_angry) - } - } else { - txtOption1.setBackgroundResource(R.drawable.search_container) - } + applyEmotionStyle(txtOption1, item.answer == item.options[0], emotion) + applyEmotionStyle(txtOption2, item.answer == item.options[1], emotion) + applyEmotionStyle(txtOption3, item.answer == item.options[2], emotion) + } + } - if (item.answer == item.options[1]) { - when(emotion){ - "HAPPY" -> txtOption2.setBackgroundResource(R.drawable.selected_option_happy) - "EXCITED" -> txtOption2.setBackgroundResource(R.drawable.selected_option_excited) - "NORMAL" -> txtOption2.setBackgroundResource(R.drawable.selected_option_normal) - "NERVOUS" -> txtOption2.setBackgroundResource(R.drawable.selected_option_container) - "ANGRY" -> txtOption2.setBackgroundResource(R.drawable.selected_option_angry) - } - } else { - txtOption2.setBackgroundResource(R.drawable.search_container) - } - if (item.answer == item.options[2]) { - when(emotion){ - "HAPPY" -> txtOption3.setBackgroundResource(R.drawable.selected_option_happy) - "EXCITED" -> txtOption3.setBackgroundResource(R.drawable.selected_option_excited) - "NORMAL" -> txtOption3.setBackgroundResource(R.drawable.selected_option_normal) - "NERVOUS" -> txtOption3.setBackgroundResource(R.drawable.selected_option_container) - "ANGRY" -> txtOption3.setBackgroundResource(R.drawable.selected_option_angry) - } - } else { - txtOption3.setBackgroundResource(R.drawable.search_container) + private fun applyEmotionStyle(view: TextView, isSelected: Boolean, emotion: String) { + if (isSelected) { + when (emotion) { + "HAPPY" -> view.setBackgroundResource(R.drawable.selected_option_happy) + "EXCITED" -> view.setBackgroundResource(R.drawable.selected_option_excited) + "NORMAL" -> view.setBackgroundResource(R.drawable.selected_option_normal) + "NERVOUS" -> view.setBackgroundResource(R.drawable.selected_option_container) + "ANGRY" -> view.setBackgroundResource(R.drawable.selected_option_angry) + else -> view.setBackgroundResource(R.drawable.search_container) } + } else { + view.setBackgroundResource(R.drawable.search_container) } } - override fun getItemCount(): Int { - return cardList.size + fun mapQuestionType(type: String): Int { + return when (type) { + "LONG_ANSWER" -> 1 + "SHORT_ANSWER" -> 2 + "OPTIONAL" -> 3 + else -> 4 + } } -} \ No newline at end of file +} diff --git a/app/src/main/java/com/toyou/toyouandroid/presentation/fragment/mypage/MypageFragment.kt b/app/src/main/java/com/toyou/toyouandroid/presentation/fragment/mypage/MypageFragment.kt index 0a4ce327..2642091b 100644 --- a/app/src/main/java/com/toyou/toyouandroid/presentation/fragment/mypage/MypageFragment.kt +++ b/app/src/main/java/com/toyou/toyouandroid/presentation/fragment/mypage/MypageFragment.kt @@ -21,6 +21,7 @@ import com.toyou.toyouandroid.databinding.FragmentMypageBinding import com.toyou.toyouandroid.presentation.base.MainActivity import com.toyou.toyouandroid.presentation.fragment.onboarding.SignupNicknameViewModel import com.toyou.toyouandroid.data.onboarding.service.AuthService +import com.toyou.toyouandroid.domain.home.repository.HomeRepository import com.toyou.toyouandroid.network.AuthNetworkModule import com.toyou.toyouandroid.network.NetworkModule import com.toyou.toyouandroid.presentation.viewmodel.AuthViewModelFactory @@ -74,10 +75,11 @@ class MypageFragment : Fragment() { val tokenStorage = TokenStorage(requireContext()) val authService: AuthService = NetworkModule.getClient().create(AuthService::class.java) val tokenManager = TokenManager(authService, tokenStorage) + val homeRepository = HomeRepository() homeViewModel = ViewModelProvider( this, - HomeViewModelFactory(tokenManager) + HomeViewModelFactory(tokenManager, homeRepository) )[HomeViewModel::class.java] sharedPreferences = requireActivity().getSharedPreferences("FCM_PREFERENCES", Context.MODE_PRIVATE) diff --git a/app/src/main/java/com/toyou/toyouandroid/presentation/fragment/mypage/ProfileFragment.kt b/app/src/main/java/com/toyou/toyouandroid/presentation/fragment/mypage/ProfileFragment.kt index e876dad8..bd1934ee 100644 --- a/app/src/main/java/com/toyou/toyouandroid/presentation/fragment/mypage/ProfileFragment.kt +++ b/app/src/main/java/com/toyou/toyouandroid/presentation/fragment/mypage/ProfileFragment.kt @@ -20,6 +20,7 @@ import com.toyou.toyouandroid.databinding.FragmentProfileBinding import com.toyou.toyouandroid.presentation.base.MainActivity import com.toyou.toyouandroid.data.onboarding.service.AuthService import com.toyou.toyouandroid.domain.create.repository.CreateRepository +import com.toyou.toyouandroid.domain.home.repository.HomeRepository import com.toyou.toyouandroid.network.AuthNetworkModule import com.toyou.toyouandroid.network.NetworkModule import com.toyou.toyouandroid.presentation.viewmodel.AuthViewModelFactory @@ -63,12 +64,13 @@ class ProfileFragment : Fragment() { val tokenManager = TokenManager(authService, tokenStorage) val createService = AuthNetworkModule.getClient().create(CreateService::class.java) val createRepository = CreateRepository(createService) + val homeRepository = HomeRepository() viewModel = ViewModelProvider( this, HomeViewModelFactory( - tokenManager + tokenManager, homeRepository ) )[ProfileViewModel::class.java] diff --git a/app/src/main/java/com/toyou/toyouandroid/presentation/fragment/onboarding/SignupNicknameFragment.kt b/app/src/main/java/com/toyou/toyouandroid/presentation/fragment/onboarding/SignupNicknameFragment.kt index e21bea6c..fcb90b41 100644 --- a/app/src/main/java/com/toyou/toyouandroid/presentation/fragment/onboarding/SignupNicknameFragment.kt +++ b/app/src/main/java/com/toyou/toyouandroid/presentation/fragment/onboarding/SignupNicknameFragment.kt @@ -16,6 +16,7 @@ import androidx.navigation.fragment.findNavController import com.toyou.toyouandroid.R import com.toyou.toyouandroid.data.onboarding.service.AuthService import com.toyou.toyouandroid.databinding.FragmentSignupnicknameBinding +import com.toyou.toyouandroid.domain.home.repository.HomeRepository import com.toyou.toyouandroid.network.NetworkModule import com.toyou.toyouandroid.presentation.base.MainActivity import com.toyou.toyouandroid.presentation.fragment.home.HomeViewModel @@ -47,10 +48,11 @@ class SignupNicknameFragment : Fragment() { val tokenStorage = TokenStorage(requireContext()) val authService: AuthService = NetworkModule.getClient().create(AuthService::class.java) val tokenManager = TokenManager(authService, tokenStorage) + val homeRepository = HomeRepository() homeViewModel = ViewModelProvider( this, - HomeViewModelFactory(tokenManager) + HomeViewModelFactory(tokenManager, homeRepository) )[HomeViewModel::class.java] binding.viewModel = viewModel diff --git a/app/src/main/java/com/toyou/toyouandroid/presentation/fragment/onboarding/SplashFragment.kt b/app/src/main/java/com/toyou/toyouandroid/presentation/fragment/onboarding/SplashFragment.kt index 1ca989ed..a61f246f 100644 --- a/app/src/main/java/com/toyou/toyouandroid/presentation/fragment/onboarding/SplashFragment.kt +++ b/app/src/main/java/com/toyou/toyouandroid/presentation/fragment/onboarding/SplashFragment.kt @@ -3,7 +3,6 @@ package com.toyou.toyouandroid.presentation.fragment.onboarding import android.os.Bundle import android.os.Handler import android.os.Looper -import android.util.Log import android.view.LayoutInflater import android.view.View import android.view.ViewGroup @@ -15,7 +14,6 @@ import androidx.navigation.Navigation import androidx.navigation.fragment.findNavController import com.toyou.toyouHoandroid.data.create.service.CreateService import com.toyou.toyouandroid.R -import com.toyou.toyouandroid.data.UserDatabase import com.toyou.toyouandroid.databinding.FragmentSplashBinding import com.toyou.toyouandroid.presentation.base.MainActivity import com.toyou.toyouandroid.network.NetworkModule @@ -38,7 +36,6 @@ class SplashFragment : Fragment() { private val binding: FragmentSplashBinding get() = requireNotNull(_binding){"FragmentSplashBinding -> null"} - private lateinit var database: UserDatabase private lateinit var loginViewModel: LoginViewModel private lateinit var userViewModel: UserViewModel @@ -91,7 +88,6 @@ class SplashFragment : Fragment() { override fun onViewCreated(view: View, savedInstanceState: Bundle?) { super.onViewCreated(view, savedInstanceState) - database = UserDatabase.getDatabase(requireContext()) (requireActivity() as MainActivity).hideBottomNavigation(true) diff --git a/app/src/main/java/com/toyou/toyouandroid/presentation/fragment/record/friend/FriendCardDetailFragment.kt b/app/src/main/java/com/toyou/toyouandroid/presentation/fragment/record/friend/FriendCardDetailFragment.kt index f1351f00..e327d4ac 100644 --- a/app/src/main/java/com/toyou/toyouandroid/presentation/fragment/record/friend/FriendCardDetailFragment.kt +++ b/app/src/main/java/com/toyou/toyouandroid/presentation/fragment/record/friend/FriendCardDetailFragment.kt @@ -79,7 +79,7 @@ class FriendCardDetailFragment : Fragment() { // 카드 미리 보기 설정 friendCardViewModel.previewCards.observe(viewLifecycleOwner) { previewCards -> listAdapter.setCards(previewCards) - Timber.tag("CardInfoFragment").d(previewCards.toString()) + Timber.tag("FriendCardDetailFragment").d(previewCards.toString()) } // 카드 주인 정보 설정 diff --git a/app/src/main/java/com/toyou/toyouandroid/presentation/viewmodel/HomeViewModelFactory.kt b/app/src/main/java/com/toyou/toyouandroid/presentation/viewmodel/HomeViewModelFactory.kt index fd2c7dec..514b1ce7 100644 --- a/app/src/main/java/com/toyou/toyouandroid/presentation/viewmodel/HomeViewModelFactory.kt +++ b/app/src/main/java/com/toyou/toyouandroid/presentation/viewmodel/HomeViewModelFactory.kt @@ -2,13 +2,15 @@ package com.toyou.toyouandroid.presentation.viewmodel import androidx.lifecycle.ViewModel import androidx.lifecycle.ViewModelProvider +import com.toyou.toyouandroid.domain.home.repository.HomeRepository import com.toyou.toyouandroid.presentation.fragment.emotionstamp.HomeOptionViewModel import com.toyou.toyouandroid.presentation.fragment.home.HomeViewModel import com.toyou.toyouandroid.presentation.fragment.mypage.ProfileViewModel import com.toyou.toyouandroid.utils.TokenManager class HomeViewModelFactory( - private val tokenManager: TokenManager + private val tokenManager: TokenManager, + private val repository: HomeRepository ) : ViewModelProvider.Factory { override fun create(modelClass: Class): T { if (modelClass.isAssignableFrom(HomeOptionViewModel::class.java)) { @@ -16,7 +18,7 @@ class HomeViewModelFactory( return HomeOptionViewModel(tokenManager) as T } else if (modelClass.isAssignableFrom(HomeViewModel::class.java)) { @Suppress("UNCHECKED_CAST") - return HomeViewModel(tokenManager) as T + return HomeViewModel(tokenManager, repository) as T } else if (modelClass.isAssignableFrom(ProfileViewModel::class.java)) { @Suppress("UNCHECKED_CAST") return ProfileViewModel(tokenManager) as T diff --git a/app/src/main/res/layout/fragment_home.xml b/app/src/main/res/layout/fragment_home.xml index fce1e208..ab30e93d 100644 --- a/app/src/main/res/layout/fragment_home.xml +++ b/app/src/main/res/layout/fragment_home.xml @@ -202,7 +202,7 @@ + + + type="com.toyou.toyouandroid.data.home.dto.response.YesterdayCard" /> + android:layout_marginTop="8dp" + > @@ -49,8 +48,7 @@ style="@style/gangwon10" android:layout_width="wrap_content" android:layout_height="wrap_content" - android:layout_marginStart="5dp" - android:layout_marginTop="10dp" + android:layout_marginStart="6dp" android:layout_toEndOf="@+id/item_image" android:layout_toRightOf="@id/item_image" android:text="240509" @@ -62,7 +60,7 @@ android:layout_width="wrap_content" android:layout_height="wrap_content" android:layout_below="@+id/item_title" - android:layout_marginStart="5dp" + android:layout_marginStart="6dp" android:layout_toEndOf="@+id/item_image" android:layout_toRightOf="@+id/item_image" android:text="To.xxx" @@ -73,9 +71,9 @@ android:layout_width="match_parent" android:layout_height="wrap_content" android:layout_below="@+id/item_detail" - android:layout_marginStart="10dp" - android:layout_marginTop="20dp" - android:layout_marginEnd="10dp" + android:layout_marginStart="7dp" + android:layout_marginTop="9dp" + android:layout_marginEnd="7dp" android:divider="#00000000" /> @@ -102,9 +100,11 @@ android:layout_height="wrap_content" android:textColor="@color/black" style="@style/gangwon16" + android:text="닉네임" app:layout_constraintStart_toStartOf="parent" app:layout_constraintEnd_toEndOf="parent" - app:layout_constraintTop_toBottomOf="@+id/card_view" /> + app:layout_constraintTop_toBottomOf="@id/card_view" /> + \ No newline at end of file diff --git a/app/src/main/res/layout/item_yesterday_option_three.xml b/app/src/main/res/layout/item_yesterday_option_three.xml new file mode 100644 index 00000000..2fdc7118 --- /dev/null +++ b/app/src/main/res/layout/item_yesterday_option_three.xml @@ -0,0 +1,81 @@ + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/app/src/main/res/layout/item_yesterday_option_two.xml b/app/src/main/res/layout/item_yesterday_option_two.xml new file mode 100644 index 00000000..2f5150ab --- /dev/null +++ b/app/src/main/res/layout/item_yesterday_option_two.xml @@ -0,0 +1,65 @@ + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/app/src/main/res/layout/item_yesterday_qa.xml b/app/src/main/res/layout/item_yesterday_qa.xml new file mode 100644 index 00000000..ce36bf44 --- /dev/null +++ b/app/src/main/res/layout/item_yesterday_qa.xml @@ -0,0 +1,42 @@ + + + + + + + + + + + + + + \ No newline at end of file diff --git a/app/src/main/res/values/font_styles.xml b/app/src/main/res/values/font_styles.xml index a3f094f4..df1e0374 100644 --- a/app/src/main/res/values/font_styles.xml +++ b/app/src/main/res/values/font_styles.xml @@ -1,5 +1,13 @@ + + +