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

[refactor] 이름 및 패키지 정리, Type-Safe Navigation 적용 #168

Open
wants to merge 43 commits into
base: develop
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
43 commits
Select commit Hold shift + click to select a range
939f82d
[chore] 패키지 분리, 유스케이스 수정
miller198 Jan 5, 2025
c69904b
[refactor] FavoriteAction 파일 분리
miller198 Jan 5, 2025
7a3aac3
[refactor] Search feature 분리
Jan 5, 2025
fe45315
[style] 파라미터 순서 변경
Jan 5, 2025
d0a3186
[style] 오타 수정
Jan 5, 2025
d09877a
[refactor] 유스케이스 이름 수정 및 통합
Jan 5, 2025
362e1df
[refactor] Navigation 정리 중
Jan 5, 2025
cc5a67f
[refactor] Navigation 정리 중
Jan 7, 2025
b120ff7
[refactor] Route 정리
Jan 7, 2025
ad70c73
[feature] MainNavigator 클래스
Jan 7, 2025
0853192
[feature] 지도화면 Bottom Navigation Tab
miller198 Jan 18, 2025
c3ec27d
[refactor] 파일 정리, Navigation 정리
miller198 Jan 19, 2025
f90f54a
[refactor] UseCase에서 collect
miller198 Jan 20, 2025
26a8565
[refactor] @Serialization 어노테이션
miller198 Jan 21, 2025
166a40d
Merge branch 'develop' into feature/module
miller198 Jan 21, 2025
d377149
[refactor] merge중 빠진것 수정
miller198 Jan 21, 2025
6a076ee
[refactor] 빠진 루트 추가
miller198 Jan 23, 2025
0b901f1
[refactor] 실행 문제 해결
miller198 Jan 24, 2025
ad911da
[refactor] MapBottomBar 이름변경
miller198 Jan 24, 2025
b4e220f
[refactor] encode
miller198 Jan 25, 2025
dbfea34
[fix] illegalArgumentsException 해결
miller198 Jan 25, 2025
13d40b9
[style] log 제거
miller198 Jan 25, 2025
35ad243
[refactor] saveStateHandle 사용, 필요없는 코드 삭제
miller198 Jan 25, 2025
fcd0dd8
[refactor] 필요없는 코드 삭제
miller198 Jan 25, 2025
81a683e
[refactor] Song 순수 코틀린 클래스
miller198 Jan 27, 2025
fe9ca54
[refactor] usecase 추상화
miller198 Jan 30, 2025
b744e93
[refactor] PickList 공통 뷰모델 생성
miller198 Jan 30, 2025
3fec5d4
[chore] 파일 삭제 및 이동
miller198 Jan 30, 2025
f600271
[refactor] 누락 편집 기능 재반영
miller198 Jan 30, 2025
71e4d76
[refactor] 유저정보 화면, route 이름 수정
miller198 Jan 30, 2025
d1964da
[refactor] 유저정보 화면, route 이름 수정
miller198 Jan 30, 2025
55a6d62
[refactor] 패키지 정정, 함수명 변경
miller198 Jan 30, 2025
7f6e6f5
[style] 필요없는 import 삭제
miller198 Jan 30, 2025
f52bd53
[chore] 필요없는 파일 삭제
miller198 Jan 30, 2025
649d16b
[refactor] 함수 정리, 패키지 정리
miller198 Jan 30, 2025
f44a331
[refactor] 변수 타입 변경
miller198 Jan 30, 2025
97b4349
[style] 필요없는 코드 삭제
miller198 Jan 30, 2025
15c54f1
[refactor] 컴포즈함수 이름 변경
miller198 Jan 30, 2025
5c9c66d
[fix] detail 화면 뒤로가기 수정
miller198 Jan 30, 2025
c189da2
[refactor] 변수 명 변경, 파라미터 명시
miller198 Jan 30, 2025
33dea53
[refactor] 내비게이션 수정
miller198 Jan 30, 2025
21a0c1f
[refactor] detail 뒤로가기 수정
miller198 Jan 30, 2025
6d4296f
[refactor] abstract class -> interface 변경
miller198 Feb 1, 2025
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
5 changes: 5 additions & 0 deletions app/build.gradle.kts
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,7 @@ plugins {
alias(libs.plugins.ksp)
alias(libs.plugins.hilt)
alias(libs.plugins.google.services)
alias(libs.plugins.kotlin.serialization)
alias(libs.plugins.firebase.crashlytics)
}

Expand Down Expand Up @@ -117,6 +118,7 @@ dependencies {
androidTestImplementation(libs.androidx.ui.test.junit4)
debugImplementation(libs.androidx.ui.tooling)
debugImplementation(libs.androidx.ui.test.manifest)
implementation(libs.kotlinx.immutable)

// Hilt
implementation(libs.hilt.android)
Expand Down Expand Up @@ -150,4 +152,7 @@ dependencies {
// Paging
implementation(libs.androidx.paging.runtime)
implementation(libs.androidx.paging.compose.android)

// Serialization
implementation(libs.kotlinx.serialization.json)
}
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
package com.squirtles.musicroad.picklist
package com.squirtles.musicroad.common.picklist

import android.content.res.Configuration
import androidx.compose.foundation.background
Expand All @@ -20,7 +20,6 @@ import androidx.compose.material3.MaterialTheme
import androidx.compose.material3.Scaffold
import androidx.compose.material3.Text
import androidx.compose.runtime.Composable
import androidx.compose.runtime.LaunchedEffect
import androidx.compose.runtime.getValue
import androidx.compose.runtime.mutableStateOf
import androidx.compose.runtime.remember
Expand All @@ -33,8 +32,6 @@ import androidx.compose.ui.graphics.Brush
import androidx.compose.ui.platform.LocalConfiguration
import androidx.compose.ui.res.stringResource
import androidx.compose.ui.unit.dp
import androidx.hilt.navigation.compose.hiltViewModel
import androidx.lifecycle.compose.collectAsStateWithLifecycle
import androidx.wear.compose.material.CircularProgressIndicator
import com.squirtles.domain.model.Order
import com.squirtles.domain.model.Pick
Expand All @@ -44,29 +41,39 @@ import com.squirtles.musicroad.common.Constants.DEFAULT_PADDING
import com.squirtles.musicroad.common.CountText
import com.squirtles.musicroad.common.DefaultTopAppBar
import com.squirtles.musicroad.common.VerticalSpacer
import com.squirtles.musicroad.common.picklist.components.DeleteSelectedPickDialog
import com.squirtles.musicroad.common.picklist.components.EditModeAction
import com.squirtles.musicroad.common.picklist.components.EditModeBottomButton
import com.squirtles.musicroad.common.picklist.components.OrderBottomSheet
import com.squirtles.musicroad.common.picklist.components.PickItem
import com.squirtles.musicroad.ui.theme.Primary
import com.squirtles.musicroad.ui.theme.White

@Composable
fun PickListScreen(
fun PickListScreenContents(
userId: String,
showOrderBottomSheet: Boolean,
selectedPicksId: Set<String>,
pickListType: PickListType,
uiState: PickListUiState,
onBackClick: () -> Unit,
onItemClick: (String) -> Unit,
pickListViewModel: PickListViewModel = hiltViewModel()
setListOrder: (Order) -> Unit,
setOrderBottomSheetVisibility: (Boolean) -> Unit,
selectAllPicks: () -> Unit,
deselectAllPicks: () -> Unit,
toggleSelectedPick: (String) -> Unit,
deleteSelectedPicks: (String) -> Unit
) {
val isLandscape = LocalConfiguration.current.orientation == Configuration.ORIENTATION_LANDSCAPE
val uiState by pickListViewModel.pickListUiState.collectAsStateWithLifecycle()
val selectedPicksId by pickListViewModel.selectedPicksId.collectAsStateWithLifecycle()

var isEditMode by rememberSaveable { mutableStateOf(false) }
var showOrderBottomSheet by rememberSaveable { mutableStateOf(false) }
var isDeletePickDialogVisible by rememberSaveable { mutableStateOf(false) }

val deactivateEditMode = remember {
{
isEditMode = false
pickListViewModel.deselectAllPicks()
deselectAllPicks()
}
}
val showDeletePickDialog = remember {
Expand All @@ -75,13 +82,6 @@ fun PickListScreen(
}
}

LaunchedEffect(Unit) {
when (pickListType) {
PickListType.FAVORITE -> pickListViewModel.fetchFavoritePicks(userId)
PickListType.CREATED -> pickListViewModel.fetchMyPicks(userId)
}
}

Scaffold(
topBar = {
DefaultTopAppBar(
Expand All @@ -98,8 +98,8 @@ fun PickListScreen(
enabled = uiState is PickListUiState.Success,
isSelectedEmpty = selectedPicksId.isEmpty(),
activateEditMode = { isEditMode = true },
selectAllPicks = { pickListViewModel.selectAllPicks() },
deselectAllPicks = { pickListViewModel.deselectAllPicks() },
selectAllPicks = { selectAllPicks() },
deselectAllPicks = { deselectAllPicks() },
)
}
)
Expand All @@ -123,8 +123,8 @@ fun PickListScreen(
}

is PickListUiState.Success -> {
val pickList = (uiState as PickListUiState.Success).pickList
val order = (uiState as PickListUiState.Success).order
val pickList = uiState.pickList
val order = uiState.order

Column(
modifier = Modifier.fillMaxSize()
Expand All @@ -138,9 +138,11 @@ fun PickListScreen(
pickList = pickList,
selectedPicksId = selectedPicksId,
order = order,
onOrderClick = { showOrderBottomSheet = true },
onOrderClick = {
setOrderBottomSheetVisibility(true)
},
onItemClick = onItemClick,
onEditModeItemClick = { pickListViewModel.toggleSelectedPick(it) },
onEditModeItemClick = toggleSelectedPick,
)

if (isEditMode) {
Expand Down Expand Up @@ -170,10 +172,8 @@ fun PickListScreen(
OrderBottomSheet(
isFavoritePicks = pickListType == PickListType.FAVORITE,
currentOrder = (uiState as PickListUiState.Success).order,
onDismissRequest = { showOrderBottomSheet = false },
onOrderClick = { order ->
pickListViewModel.setListOrder(pickListType, order)
},
onDismissRequest = { setOrderBottomSheetVisibility(false) },
onOrderClick = setListOrder,
)
}

Expand All @@ -185,7 +185,7 @@ fun PickListScreen(
onDeletePickClick = {
isEditMode = false
isDeletePickDialogVisible = false
pickListViewModel.deleteSelectedPicks(pickListType)
deleteSelectedPicks(userId)
},
)
}
Expand Down
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
package com.squirtles.musicroad.picklist
package com.squirtles.musicroad.common.picklist

enum class PickListType {
FAVORITE, CREATED
Expand Down
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
package com.squirtles.musicroad.picklist
package com.squirtles.musicroad.common.picklist

import com.squirtles.domain.model.Order
import com.squirtles.domain.model.Pick
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,101 @@
package com.squirtles.musicroad.common.picklist

import android.util.Log
import androidx.lifecycle.ViewModel
import androidx.lifecycle.viewModelScope
import com.squirtles.domain.model.Order
import com.squirtles.domain.model.Pick
import com.squirtles.domain.usecase.picklist.DeletePickListUseCaseInterface
import com.squirtles.domain.usecase.picklist.FetchPickListUseCaseInterface
import com.squirtles.domain.usecase.picklist.GetPickListOrderUseCaseInterface
import com.squirtles.domain.usecase.picklist.SavePickListOrderUseCaseInterface
import kotlinx.coroutines.async
import kotlinx.coroutines.awaitAll
import kotlinx.coroutines.flow.MutableStateFlow
import kotlinx.coroutines.flow.asStateFlow
import kotlinx.coroutines.launch

abstract class PickListViewModel(
val fetchPickListUseCase: FetchPickListUseCaseInterface,
val getPickListOrderUseCase: GetPickListOrderUseCaseInterface,
val savePickListOrderUseCase: SavePickListOrderUseCaseInterface,
val removePickUseCase: DeletePickListUseCaseInterface
) : ViewModel() {

private var pickList: List<Pick> = emptyList()

private val _pickListUiState = MutableStateFlow<PickListUiState>(PickListUiState.Loading)
val pickListUiState = _pickListUiState.asStateFlow()

private val _selectedPicksId = MutableStateFlow<Set<String>>(emptySet())
val selectedPicksId = _selectedPicksId.asStateFlow()

fun fetchPickList(userId: String) {
viewModelScope.launch {
fetchPickListUseCase(userId)
.onSuccess { picks ->
pickList = picks
sortPickList(getPickListOrderUseCase())
}
.onFailure {
_pickListUiState.emit(PickListUiState.Error)
}
}
}

private fun sortPickList(order: Order) {
_pickListUiState.value = PickListUiState.Success(
pickList = pickList.setOrderedList(order),
order = order
)
}

fun setListOrder(order: Order) {
viewModelScope.launch {
savePickListOrderUseCase(order)
sortPickList(order)
}
}

fun toggleSelectedPick(pickId: String) {
val curSelectedPicksId = _selectedPicksId.value
_selectedPicksId.value =
if (curSelectedPicksId.contains(pickId)) curSelectedPicksId - pickId else curSelectedPicksId + pickId
}

fun selectAllPicks() {
_selectedPicksId.value = pickList.map { it.id }.toSet()
}

fun deselectAllPicks() {
_selectedPicksId.value = emptySet()
}

fun deleteSelectedPicks(userId: String) {
viewModelScope.launch {
_pickListUiState.value = PickListUiState.Loading

val deleteJobList = _selectedPicksId.value.map { pickId ->
async { removePickUseCase(pickId, userId) }
}.awaitAll()

deselectAllPicks()

if (deleteJobList.all { it.isSuccess }) {
fetchPickList(userId)
} else {
_pickListUiState.value = PickListUiState.Error
Log.e("PickListViewModel", "[픽 목록] 다중 삭제 오류")
}
}
}

private fun List<Pick>.setOrderedList(order: Order): List<Pick> {
return if (pickList.isEmpty()) this
else when (order) {
Order.LATEST -> this
Order.OLDEST -> this.reversed()
Order.FAVORITE_DESC -> this.sortedByDescending { it.favoriteCount }
}
}
}
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
package com.squirtles.musicroad.picklist
package com.squirtles.musicroad.common.picklist.components

import androidx.compose.runtime.Composable
import androidx.compose.ui.res.stringResource
Expand All @@ -7,6 +7,7 @@ import com.squirtles.musicroad.R
import com.squirtles.musicroad.common.DialogTextButton
import com.squirtles.musicroad.common.HorizontalSpacer
import com.squirtles.musicroad.common.MessageAlertDialog
import com.squirtles.musicroad.common.picklist.PickListType
import com.squirtles.musicroad.ui.theme.Primary

@Composable
Expand Down
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
package com.squirtles.musicroad.picklist
package com.squirtles.musicroad.common.picklist.components

import androidx.compose.material.icons.Icons
import androidx.compose.material.icons.filled.Edit
Expand Down
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
package com.squirtles.musicroad.picklist
package com.squirtles.musicroad.common.picklist.components

import androidx.compose.foundation.layout.Row
import androidx.compose.foundation.layout.fillMaxHeight
Expand Down
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
package com.squirtles.musicroad.picklist
package com.squirtles.musicroad.common.picklist.components

import androidx.compose.foundation.clickable
import androidx.compose.foundation.layout.Arrangement
Expand Down
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
package com.squirtles.musicroad.picklist
package com.squirtles.musicroad.common.picklist.components

import androidx.compose.foundation.background
import androidx.compose.foundation.clickable
Expand Down Expand Up @@ -66,7 +66,10 @@ internal fun PickItem(
verticalAlignment = Alignment.CenterVertically
) {
AlbumImage(
imageUrl = song.getImageUrlWithSize(Constants.REQUEST_IMAGE_SIZE_DEFAULT),
imageUrl = song.getImageUrlWithSize(
Constants.REQUEST_IMAGE_SIZE_DEFAULT.width,
Constants.REQUEST_IMAGE_SIZE_DEFAULT.height
),
modifier = Modifier
.size(64.dp)
.clip(RoundedCornerShape(8.dp))
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -54,6 +54,7 @@ import androidx.compose.ui.tooling.preview.Preview
import androidx.compose.ui.unit.dp
import androidx.core.graphics.toColorInt
import androidx.core.view.WindowInsetsControllerCompat
import androidx.hilt.navigation.compose.hiltViewModel
import androidx.lifecycle.compose.collectAsStateWithLifecycle
import com.squirtles.domain.model.Song
import com.squirtles.musicroad.R
Expand All @@ -66,11 +67,12 @@ import com.squirtles.musicroad.ui.theme.White

@Composable
fun CreatePickScreen(
createPickViewModel: CreatePickViewModel,
song: Song,
onBackClick: () -> Unit,
onCreateClick: (String) -> Unit,
createPickViewModel: CreatePickViewModel = hiltViewModel(),
) {
val song = createPickViewModel.selectedSong ?: DEFAULT_SONG

val comment = createPickViewModel.comment.collectAsStateWithLifecycle()
val uiState by createPickViewModel.createPickUiState.collectAsStateWithLifecycle()
var showCreateIndicator by rememberSaveable { mutableStateOf(false) }
Expand Down Expand Up @@ -217,7 +219,7 @@ private fun CreatePickContent(
)

AlbumImage(
imageUrl = song.getImageUrlWithSize(RequestImageSize),
imageUrl = song.getImageUrlWithSize(RequestImageSize.width, RequestImageSize.height),
modifier = Modifier
.fillMaxWidth()
.padding(horizontal = 30.dp)
Expand Down
Loading