feat: 즐겨찾기 기능 프레젠테이션 레이어 추가
- MainViewModel에 즐겨찾기 토글/설정 메서드 추가 - DealItem에 즐겨찾기 버튼 및 콜백 추가 - DealListScreen에 즐겨찾기 필터 탭 추가 - 키워드 카드 색상을 옅은 붉은색으로 변경 Ultraworked with [Sisyphus](https://github.com/code-yeongyu/oh-my-opencode) Co-authored-by: Sisyphus <clio-agent@sisyphuslabs.ai>
This commit is contained in:
@@ -32,13 +32,13 @@ import com.hotdeal.alarm.util.ShareHelper
|
||||
fun DealItem(
|
||||
deal: HotDeal,
|
||||
onClick: () -> Unit,
|
||||
onFavoriteToggle: (String) -> Unit = {},
|
||||
modifier: Modifier = Modifier
|
||||
) {
|
||||
var isFavorite by remember { mutableStateOf(false) }
|
||||
val context = LocalContext.current
|
||||
|
||||
val favoriteScale by animateFloatAsState(
|
||||
targetValue = if (isFavorite) 1.2f else 1f,
|
||||
targetValue = if (deal.isFavorite) 1.2f else 1f,
|
||||
animationSpec = spring(
|
||||
dampingRatio = Spring.DampingRatioMediumBouncy,
|
||||
stiffness = Spring.StiffnessLow
|
||||
@@ -205,15 +205,15 @@ fun DealItem(
|
||||
|
||||
// 즐겨찾기 버튼
|
||||
IconButton(
|
||||
onClick = { isFavorite = !isFavorite },
|
||||
onClick = { onFavoriteToggle(deal.id) },
|
||||
modifier = Modifier
|
||||
.size(36.dp)
|
||||
.scale(favoriteScale)
|
||||
) {
|
||||
Icon(
|
||||
imageVector = if (isFavorite) Icons.Filled.Favorite else Icons.Outlined.FavoriteBorder,
|
||||
contentDescription = if (isFavorite) "즐겨찾기 제거" else "즐겨찾기 추가",
|
||||
tint = if (isFavorite)
|
||||
imageVector = if (deal.isFavorite) Icons.Filled.Favorite else Icons.Outlined.FavoriteBorder,
|
||||
contentDescription = if (deal.isFavorite) "즐겨찾기 제거" else "즐겨찾기 추가",
|
||||
tint = if (deal.isFavorite)
|
||||
MaterialTheme.colorScheme.error
|
||||
else
|
||||
MaterialTheme.colorScheme.onSurfaceVariant,
|
||||
|
||||
@@ -42,6 +42,7 @@ fun DealListScreen(
|
||||
|
||||
var searchText by remember { mutableStateOf("") }
|
||||
var selectedSiteFilter by remember { mutableStateOf<SiteType?>(null) }
|
||||
var showFavoritesOnly by remember { mutableStateOf(false) }
|
||||
var showFilterMenu by remember { mutableStateOf(false) }
|
||||
|
||||
Column(modifier = Modifier.fillMaxSize()) {
|
||||
@@ -161,6 +162,14 @@ fun DealListScreen(
|
||||
color = color
|
||||
)
|
||||
}
|
||||
|
||||
// 즐겨찾기 필터
|
||||
EnhancedFilterChip(
|
||||
selected = showFavoritesOnly,
|
||||
onClick = { showFavoritesOnly = !showFavoritesOnly },
|
||||
label = "즐겨찾기",
|
||||
color = MaterialTheme.colorScheme.error
|
||||
)
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -210,13 +219,14 @@ fun DealListScreen(
|
||||
}
|
||||
|
||||
is MainUiState.Success -> {
|
||||
val filteredDeals = remember(state.deals, searchText, selectedSiteFilter) {
|
||||
val filteredDeals = remember(state.deals, searchText, selectedSiteFilter, showFavoritesOnly) {
|
||||
state.deals.filter { deal ->
|
||||
val matchesSearch = searchText.isBlank() ||
|
||||
deal.title.contains(searchText, ignoreCase = true)
|
||||
val matchesSite = selectedSiteFilter == null ||
|
||||
deal.siteType == selectedSiteFilter
|
||||
matchesSearch && matchesSite
|
||||
val matchesFavorite = !showFavoritesOnly || deal.isFavorite
|
||||
matchesSearch && matchesSite && matchesFavorite
|
||||
}
|
||||
}
|
||||
|
||||
@@ -294,6 +304,9 @@ fun DealListScreen(
|
||||
onClick = {
|
||||
val intent = Intent(Intent.ACTION_VIEW, Uri.parse(deal.url))
|
||||
context.startActivity(intent)
|
||||
},
|
||||
onFavoriteToggle = { dealId ->
|
||||
viewModel.toggleFavorite(dealId)
|
||||
}
|
||||
)
|
||||
}
|
||||
|
||||
@@ -108,6 +108,24 @@ class MainViewModel @Inject constructor(
|
||||
viewModelScope.launch {
|
||||
keywordDao.updateEnabled(id, enabled)
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 즐겨찾기 토글
|
||||
*/
|
||||
fun toggleFavorite(dealId: String) {
|
||||
viewModelScope.launch {
|
||||
hotDealDao.toggleFavorite(dealId)
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 즐겨찾기 설정
|
||||
*/
|
||||
fun setFavorite(dealId: String, isFavorite: Boolean) {
|
||||
viewModelScope.launch {
|
||||
hotDealDao.setFavorite(dealId, isFavorite)
|
||||
}
|
||||
}
|
||||
|
||||
fun refresh() {
|
||||
|
||||
@@ -754,10 +754,7 @@ private fun EnhancedKeywordCard(
|
||||
Box(
|
||||
modifier = Modifier.size(40.dp)
|
||||
.background(
|
||||
if (keyword.isEnabled)
|
||||
MaterialTheme.colorScheme.primary
|
||||
else
|
||||
MaterialTheme.colorScheme.outline.copy(alpha = 0.5f),
|
||||
Color(0xFFFFCDD2), // 옅은 붉은색 (Light Red)
|
||||
CircleShape
|
||||
),
|
||||
contentAlignment = Alignment.Center
|
||||
@@ -765,7 +762,7 @@ private fun EnhancedKeywordCard(
|
||||
Icon(
|
||||
imageVector = Icons.Filled.Tag,
|
||||
contentDescription = null,
|
||||
tint = Color.White,
|
||||
tint = Color(0xFFD32F2F), // 붉은색 아이콘
|
||||
modifier = Modifier.size(20.dp)
|
||||
)
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user