feat: implement domain models, link health check worker, and feed screen UI components

This commit is contained in:
Bruno Charest 2026-04-23 07:40:58 -04:00
parent 83658cc6c2
commit 2198324c2d
7 changed files with 49 additions and 4 deletions

View File

@ -120,6 +120,8 @@ interface LinkDao {
SELECT * FROM links SELECT * FROM links
WHERE url NOT LIKE 'note://%' WHERE url NOT LIKE 'note://%'
AND url NOT LIKE 'https://shaarit.app/note/%' AND url NOT LIKE 'https://shaarit.app/note/%'
AND url NOT LIKE 'https://shaarit.app/config/%'
AND url NOT LIKE 'https://shaarit.app/todo/%'
AND excluded_from_health_check = 0 AND excluded_from_health_check = 0
AND (last_health_check < :timestamp OR last_health_check IS NULL) AND (last_health_check < :timestamp OR last_health_check IS NULL)
ORDER BY last_health_check ASC ORDER BY last_health_check ASC

View File

@ -41,6 +41,8 @@ class LinkHealthCheckWorker @AssistedInject constructor(
"http://shaare", "http://shaare",
"/shaare", "/shaare",
"https://shaarit.app/note/", "https://shaarit.app/note/",
"https://shaarit.app/config/",
"https://shaarit.app/todo/",
"file://", "file://",
"localhost", "localhost",
"127.0.0.1", "127.0.0.1",

View File

@ -29,6 +29,8 @@ data class ShaarliLink(
val healthStatus: HealthStatus val healthStatus: HealthStatus
get() = when { get() = when {
(url.startsWith("note://") && !url.startsWith("note://todo-")) || url.startsWith("/shaare/") || url.startsWith("https://shaarit.app/note/") -> HealthStatus.NOTE (url.startsWith("note://") && !url.startsWith("note://todo-")) || url.startsWith("/shaare/") || url.startsWith("https://shaarit.app/note/") -> HealthStatus.NOTE
url.startsWith("https://shaarit.app/config/") -> HealthStatus.CONFIG
url.startsWith("https://shaarit.app/todo/") || url.startsWith("note://todo-") -> HealthStatus.TODO
lastHealthCheck == 0L -> HealthStatus.UNTESTED lastHealthCheck == 0L -> HealthStatus.UNTESTED
linkCheckStatus == LinkCheckStatus.BROKEN -> HealthStatus.DEAD linkCheckStatus == LinkCheckStatus.BROKEN -> HealthStatus.DEAD
linkCheckStatus == LinkCheckStatus.PENDING -> HealthStatus.PENDING linkCheckStatus == LinkCheckStatus.PENDING -> HealthStatus.PENDING
@ -45,6 +47,18 @@ data class ShaarliLink(
url.startsWith("https://shaarit.app/note/") || url.startsWith("https://shaarit.app/note/") ||
tags.any { it.lowercase() == "note" || it.lowercase() == "#note" } tags.any { it.lowercase() == "note" || it.lowercase() == "#note" }
/**
* Détermine si le bookmark est une configuration app
*/
val isConfig: Boolean
get() = url.startsWith("https://shaarit.app/config/")
/**
* Détermine si le bookmark est un lien interne shaarit.app (note, todo, config, etc.)
*/
val isShaarItInternal: Boolean
get() = url.startsWith("https://shaarit.app/")
/** /**
* Détermine si le bookmark est une tâche (todo) * Détermine si le bookmark est une tâche (todo)
*/ */
@ -77,6 +91,8 @@ data class ShaarliLink(
val displayTitle: String val displayTitle: String
get() { get() {
val emoji = when { val emoji = when {
isConfig -> "⚙️"
isTodo -> ""
isNote -> "📝" isNote -> "📝"
isLocalNetwork -> "🌐" isLocalNetwork -> "🌐"
linkCheckStatus == LinkCheckStatus.BROKEN -> "🔴" linkCheckStatus == LinkCheckStatus.BROKEN -> "🔴"
@ -101,6 +117,8 @@ enum class LinkCheckStatus {
enum class HealthStatus { enum class HealthStatus {
NOTE, // C'est une note, pas un lien NOTE, // C'est une note, pas un lien
CONFIG, // Configuration app (https://shaarit.app/config/)
TODO, // Tâche (https://shaarit.app/todo/)
UNTESTED, // Jamais testé UNTESTED, // Jamais testé
OK, // Testé et fonctionnel OK, // Testé et fonctionnel
PENDING, // En attente de confirmation PENDING, // En attente de confirmation

View File

@ -333,6 +333,10 @@ fun FeedScreen(
// For tasks, navigate to task detail screen // For tasks, navigate to task detail screen
onNavigateToTodoDetail(link.id) onNavigateToTodoDetail(link.id)
} }
link.isShaarItInternal -> {
// All shaarit.app/ URLs (config, etc.): show note content
selectedLink = link
}
else -> { else -> {
// Regular link: open in browser // Regular link: open in browser
val intent = Intent(Intent.ACTION_VIEW, Uri.parse(link.url)) val intent = Intent(Intent.ACTION_VIEW, Uri.parse(link.url))

View File

@ -249,7 +249,8 @@ class FeedViewModel @Inject constructor(
val links = linkDao.getLinksByIds(selectedIds.toList()) val links = linkDao.getLinksByIds(selectedIds.toList())
for (link in links) { for (link in links) {
if (link.url.startsWith("note://") || link.url.startsWith("https://shaarit.app/note/")) { if (link.url.startsWith("note://") || link.url.startsWith("https://shaarit.app/note/") ||
link.url.startsWith("https://shaarit.app/config/") || link.url.startsWith("https://shaarit.app/todo/")) {
_linkVerificationResults.value = _linkVerificationResults.value + (link.id to LinkVerificationResult.Skipped) _linkVerificationResults.value = _linkVerificationResults.value + (link.id to LinkVerificationResult.Skipped)
continue continue
} }

View File

@ -24,6 +24,8 @@ import androidx.compose.material.icons.filled.Warning
import androidx.compose.material.icons.filled.MenuBook import androidx.compose.material.icons.filled.MenuBook
import androidx.compose.material.icons.filled.Alarm import androidx.compose.material.icons.filled.Alarm
import androidx.compose.material.icons.filled.PlayArrow import androidx.compose.material.icons.filled.PlayArrow
import androidx.compose.material.icons.filled.Settings
import androidx.compose.material.icons.filled.TaskAlt
import androidx.compose.foundation.rememberScrollState import androidx.compose.foundation.rememberScrollState
import androidx.compose.foundation.verticalScroll import androidx.compose.foundation.verticalScroll
import androidx.compose.ui.window.DialogProperties import androidx.compose.ui.window.DialogProperties
@ -1025,6 +1027,22 @@ fun HealthStatusIcon(
HealthStatus.NOTE -> { HealthStatus.NOTE -> {
// Pas d'icône pour les notes // Pas d'icône pour les notes
} }
HealthStatus.CONFIG -> {
Icon(
imageVector = Icons.Default.Settings,
contentDescription = "Configuration",
tint = Color(0xFF8B8B8B),
modifier = modifier
)
}
HealthStatus.TODO -> {
Icon(
imageVector = Icons.Default.TaskAlt,
contentDescription = "Tâche",
tint = Color(0xFF10B981),
modifier = modifier
)
}
HealthStatus.UNTESTED -> { HealthStatus.UNTESTED -> {
Icon( Icon(
imageVector = Icons.Default.HelpOutline, imageVector = Icons.Default.HelpOutline,

View File

@ -1,3 +1,3 @@
#Wed Apr 22 21:45:20 2026 #Wed Apr 22 22:23:35 2026
VERSION_NAME=2.9.0 VERSION_NAME=2.10.0
VERSION_CODE=34 VERSION_CODE=35