feat: implement dead link management UI and ViewModel to identify, verify, and organize inaccessible links
This commit is contained in:
parent
b0a6e8100b
commit
5306d8ed91
@ -25,6 +25,8 @@ import androidx.compose.animation.animateColorAsState
|
|||||||
import androidx.compose.ui.graphics.Brush
|
import androidx.compose.ui.graphics.Brush
|
||||||
import androidx.compose.ui.graphics.Color
|
import androidx.compose.ui.graphics.Color
|
||||||
import androidx.compose.ui.platform.LocalContext
|
import androidx.compose.ui.platform.LocalContext
|
||||||
|
import androidx.compose.ui.platform.LocalHapticFeedback
|
||||||
|
import androidx.compose.ui.hapticfeedback.HapticFeedbackType
|
||||||
import androidx.compose.ui.text.font.FontWeight
|
import androidx.compose.ui.text.font.FontWeight
|
||||||
import androidx.compose.ui.unit.dp
|
import androidx.compose.ui.unit.dp
|
||||||
import androidx.hilt.navigation.compose.hiltViewModel
|
import androidx.hilt.navigation.compose.hiltViewModel
|
||||||
@ -42,6 +44,7 @@ fun DeadLinksScreen(
|
|||||||
) {
|
) {
|
||||||
val pagingItems = viewModel.pagedDeadLinks.collectAsLazyPagingItems()
|
val pagingItems = viewModel.pagedDeadLinks.collectAsLazyPagingItems()
|
||||||
val context = LocalContext.current
|
val context = LocalContext.current
|
||||||
|
val haptic = LocalHapticFeedback.current
|
||||||
val snackbarHostState = remember { SnackbarHostState() }
|
val snackbarHostState = remember { SnackbarHostState() }
|
||||||
val selectedLinkIds by viewModel.selectedLinkIds.collectAsState()
|
val selectedLinkIds by viewModel.selectedLinkIds.collectAsState()
|
||||||
val isSelectionMode by viewModel.isSelectionMode.collectAsState()
|
val isSelectionMode by viewModel.isSelectionMode.collectAsState()
|
||||||
@ -256,6 +259,7 @@ fun DeadLinksScreen(
|
|||||||
dismissContent = {
|
dismissContent = {
|
||||||
DeadLinkItem(
|
DeadLinkItem(
|
||||||
link = link,
|
link = link,
|
||||||
|
selectionMode = isSelectionMode,
|
||||||
isSelected = selectedLinkIds.contains(link.id),
|
isSelected = selectedLinkIds.contains(link.id),
|
||||||
testResult = testResult,
|
testResult = testResult,
|
||||||
onItemClick = {
|
onItemClick = {
|
||||||
@ -267,6 +271,7 @@ fun DeadLinksScreen(
|
|||||||
}
|
}
|
||||||
},
|
},
|
||||||
onLongClick = {
|
onLongClick = {
|
||||||
|
haptic.performHapticFeedback(HapticFeedbackType.LongPress)
|
||||||
viewModel.toggleSelection(link.id)
|
viewModel.toggleSelection(link.id)
|
||||||
},
|
},
|
||||||
onLinkClick = { url ->
|
onLinkClick = { url ->
|
||||||
@ -276,6 +281,7 @@ fun DeadLinksScreen(
|
|||||||
onEditClick = onNavigateToEdit,
|
onEditClick = onNavigateToEdit,
|
||||||
onDeleteClick = { viewModel.deleteLink(link.id) },
|
onDeleteClick = { viewModel.deleteLink(link.id) },
|
||||||
onTagClick = { },
|
onTagClick = { },
|
||||||
|
onTogglePin = { id -> viewModel.togglePin(id) },
|
||||||
onViewClick = { }
|
onViewClick = { }
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
@ -293,6 +299,7 @@ fun DeadLinksScreen(
|
|||||||
@Composable
|
@Composable
|
||||||
private fun DeadLinkItem(
|
private fun DeadLinkItem(
|
||||||
link: com.shaarit.domain.model.ShaarliLink,
|
link: com.shaarit.domain.model.ShaarliLink,
|
||||||
|
selectionMode: Boolean,
|
||||||
isSelected: Boolean,
|
isSelected: Boolean,
|
||||||
testResult: LinkTestResult?,
|
testResult: LinkTestResult?,
|
||||||
onItemClick: () -> Unit,
|
onItemClick: () -> Unit,
|
||||||
@ -301,15 +308,11 @@ private fun DeadLinkItem(
|
|||||||
onEditClick: (Int) -> Unit,
|
onEditClick: (Int) -> Unit,
|
||||||
onDeleteClick: (Int) -> Unit,
|
onDeleteClick: (Int) -> Unit,
|
||||||
onTagClick: (String) -> Unit,
|
onTagClick: (String) -> Unit,
|
||||||
|
onTogglePin: (Int) -> Unit,
|
||||||
onViewClick: (Int) -> Unit
|
onViewClick: (Int) -> Unit
|
||||||
) {
|
) {
|
||||||
Card(
|
Card(
|
||||||
modifier = Modifier
|
modifier = Modifier.fillMaxWidth(),
|
||||||
.fillMaxWidth()
|
|
||||||
.combinedClickable(
|
|
||||||
onClick = onItemClick,
|
|
||||||
onLongClick = onLongClick
|
|
||||||
),
|
|
||||||
colors = CardDefaults.cardColors(
|
colors = CardDefaults.cardColors(
|
||||||
containerColor = if (isSelected) MaterialTheme.colorScheme.primary.copy(alpha = 0.1f) else MaterialTheme.colorScheme.surfaceVariant
|
containerColor = if (isSelected) MaterialTheme.colorScheme.primary.copy(alpha = 0.1f) else MaterialTheme.colorScheme.surfaceVariant
|
||||||
)
|
)
|
||||||
@ -318,10 +321,14 @@ private fun DeadLinkItem(
|
|||||||
ListViewItem(
|
ListViewItem(
|
||||||
link = link,
|
link = link,
|
||||||
onItemClick = onItemClick,
|
onItemClick = onItemClick,
|
||||||
|
onItemLongClick = onLongClick,
|
||||||
|
selectionMode = selectionMode,
|
||||||
|
isSelected = isSelected,
|
||||||
onLinkClick = onLinkClick,
|
onLinkClick = onLinkClick,
|
||||||
onEditClick = { onEditClick(link.id) },
|
onEditClick = { onEditClick(link.id) },
|
||||||
onDeleteClick = { onDeleteClick(link.id) },
|
onDeleteClick = { onDeleteClick(link.id) },
|
||||||
onTagClick = onTagClick,
|
onTagClick = onTagClick,
|
||||||
|
onTogglePin = onTogglePin,
|
||||||
onViewClick = { onViewClick(link.id) }
|
onViewClick = { onViewClick(link.id) }
|
||||||
)
|
)
|
||||||
|
|
||||||
|
|||||||
@ -101,6 +101,21 @@ class DeadLinksViewModel @Inject constructor(
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fun togglePin(id: Int) {
|
||||||
|
viewModelScope.launch {
|
||||||
|
linkDao.getLinkById(id)?.let { link ->
|
||||||
|
val newPinned = !link.isPinned
|
||||||
|
val newTags = if (newPinned) {
|
||||||
|
if ("shaarli-pin" !in link.tags) link.tags + "shaarli-pin" else link.tags
|
||||||
|
} else {
|
||||||
|
link.tags - "shaarli-pin"
|
||||||
|
}
|
||||||
|
linkDao.updatePinStatus(id, newPinned)
|
||||||
|
linkDao.updateLinkTags(id, newTags)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
fun deleteLink(id: Int) {
|
fun deleteLink(id: Int) {
|
||||||
viewModelScope.launch {
|
viewModelScope.launch {
|
||||||
linkRepository.deleteLink(id)
|
linkRepository.deleteLink(id)
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user