diff --git a/app/build.gradle.kts b/app/build.gradle.kts index b0d8d35..6fbfbe8 100644 --- a/app/build.gradle.kts +++ b/app/build.gradle.kts @@ -128,4 +128,6 @@ dependencies { // dot indicator implementation("com.tbuonomo:dotsindicator:5.0") + + implementation("com.google.android.flexbox:flexbox:3.0.0") } \ No newline at end of file diff --git a/app/src/main/java/com/team/score/API/request/record/FeedUploadRequest.kt b/app/src/main/java/com/team/score/API/request/record/FeedUploadRequest.kt index f0042f5..71b871c 100644 --- a/app/src/main/java/com/team/score/API/request/record/FeedUploadRequest.kt +++ b/app/src/main/java/com/team/score/API/request/record/FeedUploadRequest.kt @@ -7,9 +7,9 @@ data class FeedUploadRequest( var othersId: List?, var distance: Int, var reducedKcal: Int, - var location: String, - var weather: String, - var temperature: Int, - var fineDust: String, + var location: String?, + var weather: String?, + var temperature: Int?, + var fineDust: String?, var feeling: String? -) +) \ No newline at end of file diff --git a/app/src/main/java/com/team/score/API/response/record/FeedEmotionResponse.kt b/app/src/main/java/com/team/score/API/response/record/FeedEmotionResponse.kt index e75610e..1dfac1e 100644 --- a/app/src/main/java/com/team/score/API/response/record/FeedEmotionResponse.kt +++ b/app/src/main/java/com/team/score/API/response/record/FeedEmotionResponse.kt @@ -5,5 +5,4 @@ data class FeedEmotionResponse( val agentProfileImgUrl: String, val agentNickname: String, val emotionType: String, // "LIKE", "BEST", "SUPPORT", "CONGRAT" - val reactedAt: String ) diff --git a/app/src/main/java/com/team/score/Group/GroupMateListFragment.kt b/app/src/main/java/com/team/score/Group/GroupMateListFragment.kt index ee793d2..559be57 100644 --- a/app/src/main/java/com/team/score/Group/GroupMateListFragment.kt +++ b/app/src/main/java/com/team/score/Group/GroupMateListFragment.kt @@ -105,7 +105,9 @@ class GroupMateListFragment : Fragment() { override fun onItemClick(position: Int) { val userId = getGroupUnexercisedMateInfo?.get(position)?.userId ?: 0 - homeViewModel.batonGroupMember(mainActivity, userId) + homeViewModel.batonGroupMember(mainActivity, userId) { + + } } } } diff --git a/app/src/main/java/com/team/score/Group/GroupSearchFragment.kt b/app/src/main/java/com/team/score/Group/GroupSearchFragment.kt index d896067..ab76a20 100644 --- a/app/src/main/java/com/team/score/Group/GroupSearchFragment.kt +++ b/app/src/main/java/com/team/score/Group/GroupSearchFragment.kt @@ -62,7 +62,16 @@ class GroupSearchFragment : Fragment() { // 검색 if(editTextSearch.text.isNotEmpty()) { keyword = editTextSearch.text.toString() - viewModel.searchSchoolGroup(mainActivity, schoolId, keyword) + + recyclerViewSearchResult.visibility = View.VISIBLE + textViewSearchTitle.text = "‘${keyword}’ 검색 결과" + + viewModel.searchSchoolGroup(mainActivity, schoolId, keyword) { + layoutSearchResult.visibility = View.VISIBLE + recyclerViewSearchResult.visibility = View.GONE + layoutSearchResultEmpty.visibility = View.VISIBLE + layoutSearchEmpty.visibility = View.GONE + } } true @@ -72,8 +81,19 @@ class GroupSearchFragment : Fragment() { editTextSearch.text.clear() layoutSearchEmpty.visibility = View.VISIBLE layoutSearchResult.visibility = View.GONE + layoutSearchResultEmpty.visibility = View.GONE + + searchKewordUiUpdate() + searchKewordAdapter.updateList(MyApplication.preferences.getRecentSearchesLimited(mainActivity)) } + + buttonSearchOtherGroup.setOnClickListener { + editTextSearch.text.clear() + layoutSearchEmpty.visibility = View.VISIBLE + layoutSearchResult.visibility = View.GONE + layoutSearchResultEmpty.visibility = View.GONE + } } } @@ -123,13 +143,30 @@ class GroupSearchFragment : Fragment() { } searchKewordAdapter = RecentSearchGroupKeywordAdapter(mainActivity, MyApplication.preferences.getRecentSearchesLimited(mainActivity)).apply { - itemClickListener = object : RecentSearchGroupKeywordAdapter.OnItemClickListener { - override fun onItemClick(position: Int) { - keyword = MyApplication.preferences.getRecentSearchesLimited(mainActivity).get(position) - binding.searchBar.editTextSearch.setText(keyword) - viewModel.searchSchoolGroup(mainActivity, schoolId, keyword) + itemClickListener = object : RecentSearchGroupKeywordAdapter.OnItemClickListener { + override fun onItemClick(position: Int) { + // 검색어 클릭 시 + keyword = MyApplication.preferences.getRecentSearchesLimited(mainActivity)[position] + binding.run { + searchBar.editTextSearch.setText(keyword) + recyclerViewSearchResult.visibility = View.VISIBLE + textViewSearchTitle.text = "‘${keyword}’ 검색 결과" + } + viewModel.searchSchoolGroup(mainActivity, schoolId, keyword) { + binding.run { + layoutSearchResult.visibility = View.VISIBLE + recyclerViewSearchResult.visibility = View.GONE + layoutSearchResultEmpty.visibility = View.VISIBLE + layoutSearchEmpty.visibility = View.GONE + } + } + } + + override fun onDeleteClick(position: Int) { + // 삭제 시 동작 필요 시 작성 + searchKewordUiUpdate() + } } - } } recommendGroupAdapter = SearchGroupAdapter(mainActivity, getRecommendGroupInfo).apply { @@ -195,7 +232,6 @@ class GroupSearchFragment : Fragment() { binding.run { layoutSearchResult.visibility = View.VISIBLE layoutSearchEmpty.visibility = View.GONE - textViewSearchTitle.text = "‘${keyword}’ 검색 결과" } searchGroupAdapter.updateList(getGroupInfo) @@ -219,6 +255,8 @@ class GroupSearchFragment : Fragment() { layoutSearchEmpty.visibility = View.VISIBLE layoutSearchResult.visibility = View.GONE + searchKewordUiUpdate() + toolbar.run { buttonBack.setOnClickListener { fragmentManager?.popBackStack() @@ -226,4 +264,16 @@ class GroupSearchFragment : Fragment() { } } } + + fun searchKewordUiUpdate() { + binding.run { + if(MyApplication.preferences.getRecentSearchesLimited(mainActivity).isEmpty()) { + textViewRecentSearchTitle.visibility = View.GONE + recyclerViewSearchWord.visibility = View.GONE + } else { + textViewRecentSearchTitle.visibility = View.VISIBLE + recyclerViewSearchWord.visibility = View.VISIBLE + } + } + } } \ No newline at end of file diff --git a/app/src/main/java/com/team/score/Group/MyGroupDetailFragment.kt b/app/src/main/java/com/team/score/Group/MyGroupDetailFragment.kt index a055420..a6d117b 100644 --- a/app/src/main/java/com/team/score/Group/MyGroupDetailFragment.kt +++ b/app/src/main/java/com/team/score/Group/MyGroupDetailFragment.kt @@ -289,12 +289,14 @@ class MyGroupDetailFragment : Fragment() { times[index].text = if (hasExercise) timeText else "" // 기록 없으면 시간 텍스트 없음 times[index].visibility = if (hasExercise) View.VISIBLE else View.GONE spaces[index].visibility = if (hasExercise) View.VISIBLE else View.GONE - val graphWidth = (37 * resources.displayMetrics.density).toInt() + if(!hasExercise) { + val graphWidth = (37 * resources.displayMetrics.density).toInt() - graphs[index].layoutParams = graphs[index].layoutParams.apply { - width = graphWidth + graphs[index].layoutParams = graphs[index].layoutParams.apply { + width = graphWidth + } + graphs[index].requestLayout() // 레이아웃 갱신 } - graphs[index].requestLayout() // 레이아웃 갱신 Glide.with(profiles[index].context) diff --git a/app/src/main/java/com/team/score/Group/MyGroupRankingFragment.kt b/app/src/main/java/com/team/score/Group/MyGroupRankingFragment.kt index 9af57a5..07cb4c8 100644 --- a/app/src/main/java/com/team/score/Group/MyGroupRankingFragment.kt +++ b/app/src/main/java/com/team/score/Group/MyGroupRankingFragment.kt @@ -193,7 +193,8 @@ class MyGroupRankingFragment : Fragment() { binding.run { if(myRanking != null) { layoutGroupMyRanking.run { - textViewGroupTotalExerciseTimeValue.text = "${myRanking.weeklyExerciseTime?.div(60)}시간" + var time = if(myRanking.weeklyExerciseTime == 0.0) 0 else myRanking.weeklyExerciseTime?.div(60)?.toInt() + textViewGroupTotalExerciseTimeValue.text = "${time}시간" textViewGroupLevelValue.text = "${myRanking.weeklyLevelIncrement}" textViewGroupRankingValue.text = "${myRanking.rankNum}위" } diff --git a/app/src/main/java/com/team/score/Group/adapter/GroupMemberOthersRankingAdapter.kt b/app/src/main/java/com/team/score/Group/adapter/GroupMemberOthersRankingAdapter.kt index d3198ea..449d536 100644 --- a/app/src/main/java/com/team/score/Group/adapter/GroupMemberOthersRankingAdapter.kt +++ b/app/src/main/java/com/team/score/Group/adapter/GroupMemberOthersRankingAdapter.kt @@ -61,13 +61,19 @@ class GroupMemberOthersRankingAdapter( if((item?.changedAmount ?: 0) < 0) { imageViewRankingChange.setImageResource(R.drawable.ic_arrow_down_blue) - textViewRankingChange.text = "${(item?.changedAmount ?: 0)}" + textViewRankingChange.run { + text = "${-(item?.changedAmount ?: 0)}" + setTextColor(resources.getColor(R.color.blue)) + } } else if((item?.changedAmount ?: 0) == 0) { imageViewRankingChange.visibility = View.INVISIBLE textViewRankingChange.visibility = View.INVISIBLE } else { imageViewRankingChange.setImageResource(R.drawable.ic_arrow_up_red) - textViewRankingChange.text = "${(item?.changedAmount ?: 0)}" + textViewRankingChange.run { + text = "${(item?.changedAmount ?: 0)}" + setTextColor(resources.getColor(R.color.red)) + } } } } diff --git a/app/src/main/java/com/team/score/Group/adapter/RecentSearchGroupKeywordAdapter.kt b/app/src/main/java/com/team/score/Group/adapter/RecentSearchGroupKeywordAdapter.kt index c4d3c9f..c84bc86 100644 --- a/app/src/main/java/com/team/score/Group/adapter/RecentSearchGroupKeywordAdapter.kt +++ b/app/src/main/java/com/team/score/Group/adapter/RecentSearchGroupKeywordAdapter.kt @@ -31,7 +31,8 @@ class RecentSearchGroupKeywordAdapter( } interface OnItemClickListener { - fun onItemClick(position: Int) {} + fun onItemClick(position: Int) + fun onDeleteClick(position: Int) } var itemClickListener: OnItemClickListener? = null @@ -58,13 +59,12 @@ class RecentSearchGroupKeywordAdapter( binding.buttonDelete.setOnClickListener { MyApplication.preferences.removeRecentSearch(activity, MyApplication.preferences.getRecentSearchesLimited(activity).get(position)) updateList(MyApplication.preferences.getRecentSearchesLimited(activity)) + + itemClickListener?.onDeleteClick(adapterPosition) } binding.root.setOnClickListener { itemClickListener?.onItemClick(adapterPosition) - - // 클릭 리스너 호출 - onItemClickListener?.invoke(position) } } } diff --git a/app/src/main/java/com/team/score/Group/viewModel/GroupViewModel.kt b/app/src/main/java/com/team/score/Group/viewModel/GroupViewModel.kt index 4d189f7..e75219c 100644 --- a/app/src/main/java/com/team/score/Group/viewModel/GroupViewModel.kt +++ b/app/src/main/java/com/team/score/Group/viewModel/GroupViewModel.kt @@ -414,7 +414,7 @@ class GroupViewModel: ViewModel() { } // 학교 그룹 검색 - fun searchSchoolGroup(activity: MainActivity, schoolId: Int, keyword: String?) { + fun searchSchoolGroup(activity: MainActivity, schoolId: Int, keyword: String?, onFailure: () -> Unit) { val tempGroupList = mutableListOf() @@ -467,10 +467,13 @@ class GroupViewModel: ViewModel() { 401 -> { refreshToken( activity, - retryRequest = { searchSchoolGroup(activity, schoolId, keyword) }, + retryRequest = { searchSchoolGroup(activity, schoolId, keyword, onFailure) }, onFailure = { activity.finish() } ) } + 404 -> { + onFailure() + } } } } @@ -752,8 +755,7 @@ class GroupViewModel: ViewModel() { feed.agentId, feed.agentProfileImgUrl, feed.agentNickname, - feed.emotionType, - feed.reactedAt + feed.emotionType ) tempFeedEmotion.add(feedEmotionList) diff --git a/app/src/main/java/com/team/score/Home/HomeFragment.kt b/app/src/main/java/com/team/score/Home/HomeFragment.kt index fd942d1..94a6123 100644 --- a/app/src/main/java/com/team/score/Home/HomeFragment.kt +++ b/app/src/main/java/com/team/score/Home/HomeFragment.kt @@ -149,7 +149,7 @@ class HomeFragment : Fragment() { layoutWeeklyResult.recyclerViewGraph.apply { adapter = weeklyGraphAdapter layoutManager = LinearLayoutManager(context, RecyclerView.HORIZONTAL, false) - val spacingRatio = 0.15f + val spacingRatio = 0.18f addItemDecoration( DynamicSpacingItemDecoration(spacingRatio) ) diff --git a/app/src/main/java/com/team/score/Home/adapter/GroupRelayAdapter.kt b/app/src/main/java/com/team/score/Home/adapter/GroupRelayAdapter.kt index 75641f2..509dc2e 100644 --- a/app/src/main/java/com/team/score/Home/adapter/GroupRelayAdapter.kt +++ b/app/src/main/java/com/team/score/Home/adapter/GroupRelayAdapter.kt @@ -103,8 +103,9 @@ class GroupRelayAdapter( itemClickListener = object : GroupRelayTodayUnexercisedMemberAdapter.OnItemClickListener { override fun onItemClick(unexerciseMemberPosition: Int) { val userId = group.notExercisedUsers?.get(unexerciseMemberPosition)?.userId ?: return - viewModel.batonGroupMember(activity, userId) - updateList(group.notExercisedUsers, unexerciseMemberPosition) + viewModel.batonGroupMember(activity, userId) { + updateList(group.notExercisedUsers, unexerciseMemberPosition) + } } } } diff --git a/app/src/main/java/com/team/score/Home/viewModel/HomeViewModel.kt b/app/src/main/java/com/team/score/Home/viewModel/HomeViewModel.kt index efb5bf2..7e048a7 100644 --- a/app/src/main/java/com/team/score/Home/viewModel/HomeViewModel.kt +++ b/app/src/main/java/com/team/score/Home/viewModel/HomeViewModel.kt @@ -77,7 +77,7 @@ class HomeViewModel: ViewModel() { } // 바통 찌르기 - fun batonGroupMember(activity: Activity, receiverId: Int) { + fun batonGroupMember(activity: Activity, receiverId: Int, onSuccess: () -> Unit) { val apiClient = ApiClient(activity) val tokenManager = TokenManager(activity) @@ -95,6 +95,8 @@ class HomeViewModel: ViewModel() { isBaton.value = BatonStatus(true, receiverId) + onSuccess() + } else { // 통신이 실패한 경우(응답코드 3xx, 4xx 등) var result: Boolean? = response.body() @@ -110,7 +112,7 @@ class HomeViewModel: ViewModel() { 401 -> { refreshToken( activity, - retryRequest = { batonGroupMember(activity, receiverId) }, + retryRequest = { batonGroupMember(activity, receiverId, onSuccess) }, onFailure = { activity.finish() } ) } diff --git a/app/src/main/java/com/team/score/MainActivity.kt b/app/src/main/java/com/team/score/MainActivity.kt index 4e08ea8..8ec1548 100644 --- a/app/src/main/java/com/team/score/MainActivity.kt +++ b/app/src/main/java/com/team/score/MainActivity.kt @@ -1,35 +1,22 @@ package com.team.score -import android.Manifest import android.content.Intent -import android.net.Uri import android.os.Bundle import android.os.Handler import android.os.Looper import android.util.Log import android.view.View import android.view.inputmethod.InputMethodManager -import androidx.annotation.RequiresPermission import androidx.appcompat.app.AppCompatActivity import androidx.core.content.ContextCompat import androidx.lifecycle.ViewModelProvider -import com.google.android.gms.location.FusedLocationProviderClient -import com.google.android.gms.location.LocationCallback -import com.google.android.gms.location.LocationRequest -import com.google.android.gms.location.LocationResult -import com.google.android.gms.location.LocationServices import com.team.score.API.TokenManager import com.team.score.Group.GroupFragment import com.team.score.Home.HomeFragment -import com.team.score.Login.viewModel.UserViewModel -import com.team.score.Mypage.MypageMainFragment import com.team.score.Mypage.viewModel.MypageViewModel import com.team.score.Record.RecordFragment -import com.team.score.Record.viewModel.RecordViewModel -import com.team.score.Utils.DistanceUtil import com.team.score.Utils.GlobalApplication.Companion.firebaseAnalytics import com.team.score.Utils.MyApplication -import com.team.score.Utils.TimeUtil import com.team.score.Utils.TimerManager import com.team.score.Utils.TrackingService import com.team.score.databinding.ActivityMainBinding diff --git a/app/src/main/java/com/team/score/Mypage/MypageMainFragment.kt b/app/src/main/java/com/team/score/Mypage/MypageMainFragment.kt index b637a08..599c992 100644 --- a/app/src/main/java/com/team/score/Mypage/MypageMainFragment.kt +++ b/app/src/main/java/com/team/score/Mypage/MypageMainFragment.kt @@ -89,7 +89,7 @@ class MypageMainFragment : Fragment() { Glide.with(this@MypageMainFragment) .load(getUserInfo?.profileImgUrl) .into(imageViewProfile) - textViewNotificationTime.text = "${formatExerciseTimeToKorean(getUserInfo?.goal ?: "00:00:00")}" + textViewNotificationTime.text = "${formatExerciseTimeToKorean(getUserInfo?.goal)}" // 레벨 layout layoutLevel.run { diff --git a/app/src/main/java/com/team/score/Mypage/MypageProfileEditFragment.kt b/app/src/main/java/com/team/score/Mypage/MypageProfileEditFragment.kt index 73cb3a7..5389f5e 100644 --- a/app/src/main/java/com/team/score/Mypage/MypageProfileEditFragment.kt +++ b/app/src/main/java/com/team/score/Mypage/MypageProfileEditFragment.kt @@ -67,7 +67,6 @@ class MypageProfileEditFragment : Fragment(), SignUpGoalTimeBottomSheetListener, mainActivity = activity as MainActivity initView() - observeViewModel() // Registers a photo picker activity launcher in single-select mode. val pickMedia = @@ -198,7 +197,14 @@ class MypageProfileEditFragment : Fragment(), SignUpGoalTimeBottomSheetListener, MyApplication.userUpdateInfo?.userUpdateDto?.height = height ?: 0 MyApplication.userUpdateInfo?.userUpdateDto?.weight = weight ?: 0 - viewModel.updateUserInfo(mainActivity) + viewModel.updateUserInfo(mainActivity, + onSuccess = { + parentFragmentManager.popBackStack() + }, + onFailure = { + Toast.makeText(mainActivity, "마지막으로 학교 정보를 변경한 후 30일이 경과하지 않아 학교 정보를 수정할 수 없습니다.", Toast.LENGTH_LONG).show() + } + ) } } @@ -215,19 +221,6 @@ class MypageProfileEditFragment : Fragment(), SignUpGoalTimeBottomSheetListener, binding.buttonEdit.isEnabled = true } - fun observeViewModel() { - viewModel.run { - isUpdateUserInfo.observe(viewLifecycleOwner) { - if(it == true) { - fragmentManager?.popBackStack() - } else if(it == false) { - // 학교 정보 수정 불가 toast message - Toast.makeText(mainActivity, "마지막으로 학교 정보를 변경한 후 30일이 경과하지 않아 학교 정보를 수정할 수 없습니다.", Toast.LENGTH_LONG).show() - } - } - } - } - @RequiresApi(Build.VERSION_CODES.O) fun initView() { mainActivity.hideBottomNavigation(true) diff --git a/app/src/main/java/com/team/score/Mypage/Setting/WithdrawFragment.kt b/app/src/main/java/com/team/score/Mypage/Setting/WithdrawFragment.kt index befb370..04eae32 100644 --- a/app/src/main/java/com/team/score/Mypage/Setting/WithdrawFragment.kt +++ b/app/src/main/java/com/team/score/Mypage/Setting/WithdrawFragment.kt @@ -6,8 +6,11 @@ import android.view.LayoutInflater import android.view.View import android.view.ViewGroup import androidx.core.content.ContextCompat +import androidx.core.view.ViewCompat +import androidx.core.view.WindowInsetsCompat import androidx.core.widget.addTextChangedListener import androidx.lifecycle.ViewModelProvider +import com.team.score.API.TokenManager import com.team.score.MainActivity import com.team.score.Mypage.viewModel.MypageViewModel import com.team.score.R @@ -54,7 +57,13 @@ class WithdrawFragment : Fragment() { val result = reasons.joinToString(separator = ", ") - viewModel.withdrawal(mainActivity, result) + viewModel.withdrawal(mainActivity, result) { + + TokenManager(mainActivity).deleteAccessToken() + TokenManager(mainActivity).deleteRefreshToken() + + mainActivity.finish() + } } } diff --git a/app/src/main/java/com/team/score/Mypage/UserFeedFragment.kt b/app/src/main/java/com/team/score/Mypage/UserFeedFragment.kt index 67c73c8..28bc2c5 100644 --- a/app/src/main/java/com/team/score/Mypage/UserFeedFragment.kt +++ b/app/src/main/java/com/team/score/Mypage/UserFeedFragment.kt @@ -5,12 +5,15 @@ import android.util.Log import android.view.LayoutInflater import android.view.View import android.view.ViewGroup +import androidx.core.content.ContextCompat import androidx.fragment.app.Fragment import androidx.lifecycle.ViewModelProvider import androidx.recyclerview.widget.GridLayoutManager import androidx.recyclerview.widget.RecyclerView +import com.team.score.API.TokenManager import com.team.score.API.response.user.FeedListResponse import com.team.score.Group.OtherGroupFeedListFragment +import com.team.score.Home.viewModel.HomeViewModel import com.team.score.MainActivity import com.team.score.Mypage.Adapter.FeedAdapter import com.team.score.R @@ -27,6 +30,9 @@ class UserFeedFragment : Fragment() { private val viewModel: RecordViewModel by lazy { ViewModelProvider(this)[RecordViewModel::class.java] } + private val homeViewModel: HomeViewModel by lazy { + ViewModelProvider(requireActivity())[HomeViewModel::class.java] + } lateinit var feedAdapter: FeedAdapter @@ -77,6 +83,17 @@ class UserFeedFragment : Fragment() { .commit() } + buttonBaton.setOnClickListener { + // 바통 찌르기 + homeViewModel.batonGroupMember(mainActivity, arguments?.getInt("userId") ?: 0) { + binding.buttonBaton.run { + text = "찌르기 완료!" + backgroundTintList = + context?.let { ContextCompat.getColorStateList(it, R.color.main) } + } + } + } + recyclerViewFeed.apply { layoutManager = GridLayoutManager(context, 3) adapter = feedAdapter @@ -90,7 +107,6 @@ class UserFeedFragment : Fragment() { // 마지막 항목이 보이고, 로딩 중이 아니며, 마지막 페이지도 아닐 경우 if (!isLoading && !isLastPage && lastVisible >= totalItemCount - 1 && !(isFirstPage == true && isLastPage == true)) { - Log.d("##", "reload") isLoading = true viewModel.getFeedList(mainActivity, arguments?.getInt("userId") ?: 0, currentPage) } @@ -119,11 +135,18 @@ class UserFeedFragment : Fragment() { if(isFirstPage) { binding.run { if(feedResponse.isEmpty()) { - layoutEmptyFeed.visibility = View.VISIBLE - textViewEmptyTitle.text = "${MyApplication.userNickname}님만의 운동기록을\n채워보세요!" - recyclerViewFeed.visibility = View.GONE + if(arguments?.getInt("userId") ?: 0 == TokenManager(mainActivity).getUserId()) { + layoutEmptyFeed.visibility = View.GONE + layoutEmptyMyFeed.visibility = View.VISIBLE + textViewMyEmptyTitle.text = "${MyApplication.userNickname}님만의 운동기록을\n채워보세요!" + recyclerViewFeed.visibility = View.GONE + } else { + layoutEmptyFeed.visibility = View.VISIBLE + layoutEmptyMyFeed.visibility = View.GONE + } } else { layoutEmptyFeed.visibility = View.GONE + layoutEmptyMyFeed.visibility = View.GONE recyclerViewFeed.visibility = View.VISIBLE } } diff --git a/app/src/main/java/com/team/score/Mypage/viewModel/MypageViewModel.kt b/app/src/main/java/com/team/score/Mypage/viewModel/MypageViewModel.kt index 770bf19..2269c68 100644 --- a/app/src/main/java/com/team/score/Mypage/viewModel/MypageViewModel.kt +++ b/app/src/main/java/com/team/score/Mypage/viewModel/MypageViewModel.kt @@ -26,8 +26,6 @@ class MypageViewModel: ViewModel() { var notificationInfo: MutableLiveData = MutableLiveData() var blockedMateList = MutableLiveData>() - var isUpdateUserInfo: MutableLiveData = MutableLiveData() - var isAddMate: MutableLiveData = MutableLiveData() // 유저 정보 @@ -81,7 +79,7 @@ class MypageViewModel: ViewModel() { } // 회원 정보 수정 - fun updateUserInfo(activity: MainActivity) { + fun updateUserInfo(activity: MainActivity, onSuccess: () -> Unit, onFailure: () -> Unit) { val apiClient = ApiClient(activity) val tokenManager = TokenManager(activity) @@ -105,7 +103,7 @@ class MypageViewModel: ViewModel() { val result: String? = response.body() Log.d("##", "onResponse 성공: " + result?.toString()) - isUpdateUserInfo.value = true + onSuccess() } else { // 통신이 실패한 경우(응답코드 3xx, 4xx 등) var result: String? = response.body() @@ -116,12 +114,12 @@ class MypageViewModel: ViewModel() { Log.d("##", "Error Response: $errorBody") when(response.code()) { 400 -> { - isUpdateUserInfo.value = false + onFailure() } 401 -> { refreshToken( activity, - retryRequest = { updateUserInfo(activity) }, + retryRequest = { updateUserInfo(activity, onSuccess, onFailure) }, onFailure = { activity.finish() } ) } @@ -132,7 +130,6 @@ class MypageViewModel: ViewModel() { override fun onFailure(call: Call, t: Throwable) { // 통신 실패 Log.d("##", "onFailure 에러: " + t.message.toString()) - isUpdateUserInfo.value = null } }) } @@ -384,7 +381,7 @@ class MypageViewModel: ViewModel() { } // 회원탈퇴 - fun withdrawal(activity: MainActivity, withdrawalResult: String) { + fun withdrawal(activity: MainActivity, withdrawalResult: String, onSuccess: () -> Unit) { val apiClient = ApiClient(activity) val tokenManager = TokenManager(activity) @@ -400,7 +397,7 @@ class MypageViewModel: ViewModel() { val result: String? = response.body() Log.d("##", "onResponse 성공: " + result?.toString()) - activity.finish() + onSuccess() } else { // 통신이 실패한 경우(응답코드 3xx, 4xx 등) var result: String? = response.body() @@ -414,7 +411,7 @@ class MypageViewModel: ViewModel() { 401 -> { refreshToken( activity, - retryRequest = { withdrawal(activity, withdrawalResult) }, + retryRequest = { withdrawal(activity, withdrawalResult, onSuccess) }, onFailure = { activity.finish() } ) } diff --git a/app/src/main/java/com/team/score/OnBoarding/SplashFragment.kt b/app/src/main/java/com/team/score/OnBoarding/SplashFragment.kt index 7ac449a..12c850d 100644 --- a/app/src/main/java/com/team/score/OnBoarding/SplashFragment.kt +++ b/app/src/main/java/com/team/score/OnBoarding/SplashFragment.kt @@ -1,12 +1,16 @@ package com.team.score.OnBoarding +import android.content.Context import android.content.Intent import android.os.Bundle import android.os.Handler +import android.util.Log import androidx.fragment.app.Fragment import android.view.LayoutInflater import android.view.View import android.view.ViewGroup +import com.kakao.sdk.share.ShareClient +import com.kakao.sdk.share.WebSharerClient import com.team.score.API.TokenManager import com.team.score.API.TokenUtil import com.team.score.Login.LoginFragment @@ -27,6 +31,16 @@ class SplashFragment : Fragment() { binding = FragmentSplashBinding.inflate(layoutInflater) onboardingActivity = activity as OnboardingActivity + return binding.root + } + + override fun onResume() { + super.onResume() + + moveFragment() + } + + fun moveFragment() { Handler().postDelayed({ if(TokenManager(onboardingActivity).getEnter()) { onboardingActivity.supportFragmentManager.beginTransaction() @@ -53,7 +67,5 @@ class SplashFragment : Fragment() { } } }, 3000) - - return binding.root } } \ No newline at end of file diff --git a/app/src/main/java/com/team/score/Record/RecordFeedImageFragment.kt b/app/src/main/java/com/team/score/Record/RecordFeedImageFragment.kt index 902438c..da48b84 100644 --- a/app/src/main/java/com/team/score/Record/RecordFeedImageFragment.kt +++ b/app/src/main/java/com/team/score/Record/RecordFeedImageFragment.kt @@ -251,31 +251,34 @@ class RecordFeedImageFragment : Fragment() { private fun convertResizeImage(imageUri: Uri): Uri { val contentResolver = requireContext().contentResolver - val bitmap = MediaStore.Images.Media.getBitmap(contentResolver, imageUri) - - // 이미지 리사이즈 (절반 크기로) - val resizedBitmap = - Bitmap.createScaledBitmap(bitmap, bitmap.width / 2, bitmap.height / 2, true) + val originalBitmap = MediaStore.Images.Media.getBitmap(contentResolver, imageUri) + + // 1. 이미지 리사이즈 (너무 크면 줄이기) + val resizedBitmap = Bitmap.createScaledBitmap( + originalBitmap, + originalBitmap.width / 4, + originalBitmap.height / 4, + true + ) - // 임시 파일 생성 - val tempFile = File.createTempFile("resized_image", ".jpg", requireContext().cacheDir) + // 2. 최대 2MB 이하가 될 때까지 압축 + val maxFileSize = 2 * 1024 * 1024 // 2MB + var quality = 100 + val stream = ByteArrayOutputStream() - // 이미지 파일 쓰기 - try { - val byteArrayOutputStream = ByteArrayOutputStream() - resizedBitmap.compress(Bitmap.CompressFormat.JPEG, 90, byteArrayOutputStream) + do { + stream.reset() + resizedBitmap.compress(Bitmap.CompressFormat.JPEG, quality, stream) + quality -= 5 + } while (stream.size() > maxFileSize && quality > 10) - FileOutputStream(tempFile).use { outputStream -> - outputStream.write(byteArrayOutputStream.toByteArray()) - outputStream.flush() - } + // 3. 임시 파일 생성 후 저장 + val tempFile = File.createTempFile("resized_image", ".jpg", requireContext().cacheDir) + FileOutputStream(tempFile).use { it.write(stream.toByteArray()) } - } catch (e: Exception) { - Log.e("ImageResize", "Failed to write file: ${e.message}") - } finally { - // 메모리 해제 - resizedBitmap.recycle() - } + // 4. 메모리 해제 + resizedBitmap.recycle() + originalBitmap.recycle() return Uri.fromFile(tempFile) } diff --git a/app/src/main/java/com/team/score/Record/RecordFragment.kt b/app/src/main/java/com/team/score/Record/RecordFragment.kt index f51dc77..b480011 100644 --- a/app/src/main/java/com/team/score/Record/RecordFragment.kt +++ b/app/src/main/java/com/team/score/Record/RecordFragment.kt @@ -92,10 +92,12 @@ class RecordFragment : Fragment() { buttonRecord.setOnClickListener { firebaseAnalytics.logEvent("click_start_record", null) - isStart = mainActivity.toggleTrackingService() - binding.buttonRecord.setImageResource( - if (isStart) R.drawable.ic_temporary_stop else R.drawable.ic_start - ) + if (checkLocationPermission()) { + isStart = mainActivity.toggleTrackingService() + binding.buttonRecord.setImageResource( + if (isStart) R.drawable.ic_temporary_stop else R.drawable.ic_start + ) + } } buttonStop.setOnClickListener { if (TimerManager.startedAtIso != null) { @@ -126,8 +128,9 @@ class RecordFragment : Fragment() { // UI 상태 복원 로직 if (TimerManager.startedAtMillis != null && TimerManager.isRunning) { val now = System.currentTimeMillis() - val elapsed = ((now - TimerManager.startedAtMillis!!) / 1000).toInt() + val elapsed = ((now - TimerManager.startedAtMillis!!).toInt())/ 1000 MyApplication.recordTimer = elapsed + startTimerUIUpdater() } } @@ -154,7 +157,6 @@ class RecordFragment : Fragment() { } else { buttonRecord.setImageResource(R.drawable.ic_start) } - textViewTimer.text = TimeUtil.formatRecordTime(MyApplication.recordTimer) checkLocationPermission() diff --git a/app/src/main/java/com/team/score/Record/viewModel/RecordViewModel.kt b/app/src/main/java/com/team/score/Record/viewModel/RecordViewModel.kt index c048c8a..6a8c4db 100644 --- a/app/src/main/java/com/team/score/Record/viewModel/RecordViewModel.kt +++ b/app/src/main/java/com/team/score/Record/viewModel/RecordViewModel.kt @@ -194,8 +194,7 @@ class RecordViewModel: ViewModel() { feed.agentId, feed.agentProfileImgUrl, feed.agentNickname, - feed.emotionType, - feed.reactedAt + feed.emotionType ) tempFeedEmotion.add(feedEmotionList) diff --git a/app/src/main/java/com/team/score/Utils/TimeUtil.kt b/app/src/main/java/com/team/score/Utils/TimeUtil.kt index ecb4f40..16391bb 100644 --- a/app/src/main/java/com/team/score/Utils/TimeUtil.kt +++ b/app/src/main/java/com/team/score/Utils/TimeUtil.kt @@ -34,7 +34,9 @@ object TimeUtil { // 목표 시간 표시 포맷 @RequiresApi(Build.VERSION_CODES.O) - fun formatExerciseTimeToKorean(time: String): String { + fun formatExerciseTimeToKorean(time: String?): String { + if(time.isNullOrEmpty()) return "없음" + val formatter = DateTimeFormatter.ofPattern("HH:mm:ss") val localTime = LocalTime.parse(time, formatter) diff --git a/app/src/main/res/drawable/img_mood_cry_thick.xml b/app/src/main/res/drawable/img_mood_cry_thick.xml new file mode 100644 index 0000000..5d350ca --- /dev/null +++ b/app/src/main/res/drawable/img_mood_cry_thick.xml @@ -0,0 +1,45 @@ + + + + + + + + + + diff --git a/app/src/main/res/drawable/img_mood_empty.xml b/app/src/main/res/drawable/img_mood_empty_thick.xml similarity index 100% rename from app/src/main/res/drawable/img_mood_empty.xml rename to app/src/main/res/drawable/img_mood_empty_thick.xml diff --git a/app/src/main/res/drawable/img_mood_happy_thick.xml b/app/src/main/res/drawable/img_mood_happy_thick.xml new file mode 100644 index 0000000..2d38020 --- /dev/null +++ b/app/src/main/res/drawable/img_mood_happy_thick.xml @@ -0,0 +1,38 @@ + + + + + + + + + diff --git a/app/src/main/res/drawable/img_mood_smile.xml b/app/src/main/res/drawable/img_mood_smile_thick.xml similarity index 100% rename from app/src/main/res/drawable/img_mood_smile.xml rename to app/src/main/res/drawable/img_mood_smile_thick.xml diff --git a/app/src/main/res/layout/dialog_profile_eidt.xml b/app/src/main/res/layout/dialog_profile_eidt.xml index ee660b3..8a5e29d 100644 --- a/app/src/main/res/layout/dialog_profile_eidt.xml +++ b/app/src/main/res/layout/dialog_profile_eidt.xml @@ -69,6 +69,7 @@ android:layout_marginTop="32dp" android:fontFamily="@font/pretendard_semi_bold" android:text="학교 정보 수정은 30일에 한 번 가능해요" + android:textAlignment="center" android:textColor="@color/red" android:textSize="16sp" app:layout_constraintEnd_toEndOf="parent" diff --git a/app/src/main/res/layout/fragment_group.xml b/app/src/main/res/layout/fragment_group.xml index 1032488..32ab629 100644 --- a/app/src/main/res/layout/fragment_group.xml +++ b/app/src/main/res/layout/fragment_group.xml @@ -179,6 +179,7 @@ android:layout_height="wrap_content" android:layout_marginTop="12sp" android:fontFamily="@font/pretendard_semi_bold" + android:textAlignment="center" android:text="아직 그룹이 없어요" android:textSize="24sp" app:layout_constraintEnd_toEndOf="@+id/imageView_empty" @@ -191,6 +192,7 @@ android:layout_width="wrap_content" android:layout_height="wrap_content" android:layout_marginTop="3dp" + android:textAlignment="center" android:text="함께 운동할 그룹을 만들어볼까요?" android:textColor="@color/text_color2" app:layout_constraintEnd_toEndOf="@+id/textView_empty_title" @@ -207,6 +209,7 @@ android:paddingHorizontal="11.5dp" android:paddingVertical="10.5dp" android:text="내그룹 만들기" + android:textColor="@color/white" app:cornerRadius="8dp" app:layout_constraintEnd_toEndOf="@+id/textView_empty_description" app:layout_constraintStart_toStartOf="@+id/textView_empty_description" diff --git a/app/src/main/res/layout/fragment_group_search.xml b/app/src/main/res/layout/fragment_group_search.xml index 8158bd8..061ca69 100644 --- a/app/src/main/res/layout/fragment_group_search.xml +++ b/app/src/main/res/layout/fragment_group_search.xml @@ -26,8 +26,7 @@ app:layout_constraintStart_toStartOf="parent" app:layout_constraintTop_toBottomOf="@+id/toolbar" /> - - - - + android:orientation="vertical"> - + - + - - - - - - - + + + + + + + + + + +