feat: Add JitPack repository to dependency resolution management feat: Create ViewStyle enum for bookmark display styles feat: Implement EditLinkScreen with ViewModel for editing links feat: Add EditLinkViewModel to manage link editing state and logic feat: Create LinkItemViews for displaying links in various formats chore: Add build output and compile output logs
ShaarIt
ShaarIt est un client Android natif pour Shaarli, le gestionnaire de favoris auto-hébergé. Développé avec les technologies Android modernes, il offre une expérience mobile fluide pour gérer vos liens.
📱 Fonctionnalités
🔐 Authentification
- Connexion sécurisée à votre instance Shaarli auto-hébergée (API v1)
- Stockage chiffré des tokens JWT et secrets API via
EncryptedSharedPreferences - Génération automatique de tokens JWT avec algorithme HS512
📚 Gestion des Favoris
- Flux infini : Défilement continu avec chargement progressif (Paging 3)
- Recherche côté serveur : Recherche par termes et filtrage par tags
- Ajout rapide : Création de liens privés/publics avec description et tags
- Édition : Modification complète des liens existants
- Suppression : Gestion facile des favoris
- Détection des doublons : Alerte lors de l'ajout d'un lien existant avec option de mise à jour
🏷️ Gestion des Tags
- Vue dédiée pour parcourir tous les tags
- Compteur d'utilisation par tag
- Filtrage rapide du flux par tag
🔗 Intégration système
- Share Intent Android : Sauvegarde rapide depuis n'importe quelle app (navigateur, YouTube, etc.) via le menu Partager
- Ouverture des liens dans le navigateur par défaut
- Support des URLs partagées avec titre pré-rempli
🎨 Interface Utilisateur
- Design premium : Thème sombre moderne avec dégradés cyan/bleu
- Material Design 3 : Composants UI natifs Android
- Animations fluides : Transitions et effets visuels
- Deux modes d'affichage : Liste détaillée ou grille compacte
- Pull-to-refresh : Actualisation du flux par glissement
🛠️ Stack Technique
| Catégorie | Technologie |
|---|---|
| Langage | Kotlin 1.9.20 |
| UI | Jetpack Compose + Material Design 3 |
| Architecture | Clean Architecture + MVVM |
| Injection de dépendances | Dagger Hilt 2.48.1 |
| Réseau | Retrofit 2.9.0 + Moshi 1.15.0 + OkHttp 4.12.0 |
| Pagination | Paging 3 |
| Concurrence | Coroutines & Flow |
| Stockage sécurisé | AndroidX Security Crypto |
| Navigation | Navigation Compose |
| Compilation | Gradle 8.0+ avec KSP |
Compatibilité
- minSdk: 24 (Android 7.0)
- targetSdk: 34 (Android 14)
- compileSdk: 34
- JDK requis: 17+
📥 Installation
Prérequis utilisateur
- Un serveur Shaarli auto-hébergé (v0.12+) avec l'API v1 activée
- Un appareil Android 7.0+ ou un émulateur
Obtenir l'APK
Méthode 1 : Téléchargement direct
Récupérez le dernier APK depuis la section Releases.
Méthode 2 : Compilation depuis les sources
Prérequis de développement
- JDK 17 (ou plus récent) installé
- Android SDK installé (Platform API 34)
- Gradle 8.0+ (si
gradlewest manquant)
Étapes de compilation
-
Cloner le repository
git clone https://github.com/votre-username/ShaarIt.git cd ShaarIt -
Configurer l'emplacement du SDK Android
Si la variable
ANDROID_HOMEn'est pas définie, créez un fichierlocal.properties:# Windows echo sdk.dir=C:\Users\<Username>\AppData\Local\Android\Sdk > local.properties # Linux/macOS echo sdk.dir=/home/<username>/Android/Sdk > local.properties -
Compiler l'APK Debug
# Windows ./gradlew assembleDebug # Linux/macOS chmod +x gradlew ./gradlew assembleDebug -
L'APK se trouve dans :
app/build/outputs/apk/debug/app-debug.apk -
Installer sur l'appareil
adb install -r app/build/outputs/apk/debug/app-debug.apk
Configuration initiale de l'app
- Ouvrez l'application ShaarIt
- Entrez l'URL de votre instance Shaarli (ex:
https://monserveur.com/shaarli) - Entrez votre Secret API (trouvé dans les paramètres admin de Shaarli)
- Cliquez sur Connecter
🧑💻 Section Développement
Architecture du projet
app/src/main/java/com/shaarit/
├── core/ # Infrastructure et utilitaires
│ ├── di/ # Modules Dagger Hilt (injection de dépendances)
│ │ ├── AppModule.kt # Fournisseurs d'applications
│ │ ├── NetworkModule.kt # Configuration Retrofit/OkHttp
│ │ └── RepositoryModule.kt # Liaisons repository
│ ├── network/ # Intercepteurs réseau
│ │ ├── AuthInterceptor.kt # Injection automatique du token JWT
│ │ └── HostSelectionInterceptor.kt # Changement dynamique d'hôte
│ ├── storage/ # Stockage local sécurisé
│ │ └── TokenManager.kt # Gestion chiffrée des tokens
│ └── util/ # Utilitaires
│ └── JwtGenerator.kt # Générateur JWT HS512
├── data/ # Couche de données (Clean Architecture)
│ ├── api/ # Interface Retrofit
│ │ └── ShaarliApi.kt # Endpoints API v1
│ ├── dto/ # Data Transfer Objects (Moshi)
│ │ ├── Dtos.kt # Login, Link, Info DTOs
│ │ └── TagDto.kt # Tag DTO
│ ├── mapper/ # Convertisseurs DTO ↔ Domain
│ │ └── LinkMapper.kt
│ ├── paging/ # Sources de pagination
│ │ └── LinkPagingSource.kt # Paging 3 pour le flux
│ └── repository/ # Implémentations des repositories
│ ├── AuthRepositoryImpl.kt
│ └── LinkRepositoryImpl.kt
├── domain/ # Couche métier (indépendante des frameworks)
│ ├── model/ # Modèles de domaine
│ │ ├── Models.kt # Credentials, ShaarliLink
│ │ ├── ShaarliTag.kt
│ │ └── ViewStyle.kt # Enum modes d'affichage
│ ├── repository/ # Interfaces de repository
│ │ ├── AuthRepository.kt
│ │ └── LinkRepository.kt
│ └── usecase/ # Cas d'utilisation
│ └── LoginUseCase.kt
├── presentation/ # Couche présentation (UI)
│ ├── auth/ # Écran de connexion
│ │ ├── LoginScreen.kt
│ │ └── LoginViewModel.kt
│ ├── feed/ # Flux principal
│ │ ├── FeedScreen.kt
│ │ ├── FeedViewModel.kt
│ │ └── LinkItemViews.kt # Composants de carte de lien
│ ├── add/ # Ajout de lien
│ │ ├── AddLinkScreen.kt
│ │ └── AddLinkViewModel.kt
│ ├── edit/ # Édition de lien
│ │ ├── EditLinkScreen.kt
│ │ └── EditLinkViewModel.kt
│ ├── tags/ # Gestion des tags
│ │ ├── TagsScreen.kt
│ │ └── TagsViewModel.kt
│ └── nav/ # Navigation Compose
│ └── NavGraph.kt # Routes et navigation
├── ui/ # Composants UI réutilisables
│ ├── components/ # Composants custom premium
│ │ └── PremiumComponents.kt # GlassCard, GradientButton, etc.
│ └── theme/ # Thème Material Design 3
│ ├── Theme.kt # Couleurs et thème sombre
│ └── Type.kt # Typographie
├── MainActivity.kt # Point d'entrée avec gestion Share Intent
└── ShaarItApp.kt # Application Hilt
Flux d'authentification JWT
┌─────────────┐ ┌──────────────┐ ┌─────────────────┐
│ Utilisateur │────▶│ LoginScreen │────▶│ LoginViewModel │
└─────────────┘ └──────────────┘ └─────────────────┘
│
┌───────────────────────────────┘
▼
┌─────────────┐ ┌──────────────┐ ┌─────────────────┐
│ TokenManager│◀────│AuthRepository│◀────│ LoginUseCase │
└─────────────┘ └──────────────┘ └─────────────────┘
│
▼
┌─────────────────────────┐
│ EncryptedSharedPreferences│ (AES256_GCM)
└─────────────────────────┘
Le token JWT est généré localement avec l'algorithme HS512 :
- Header :
{"typ":"JWT","alg":"HS512"} - Payload :
{"iat": <unix_timestamp>} - Signature : HMAC-SHA512(base64url(header) + "." + base64url(payload), apiSecret)
Pagination avec Paging 3
┌─────────────┐ ┌─────────────────┐ ┌─────────────────┐
│ FeedScreen │────▶│ FeedViewModel │────▶│ LinkRepository │
└─────────────┘ └─────────────────┘ └─────────────────┘
│
┌──────────────────────────────────┘
▼
┌─────────────┐ ┌──────────────┐ ┌─────────────────┐
│ lazyPagingItems│◀──│ Pager │◀────│ LinkPagingSource│
└─────────────┘ └──────────────┘ └─────────────────┘
│
▼
┌──────────────┐
│ ShaarliApi │
└──────────────┘
Configuration réseau dynamique
L'application utilise un pattern d'intercepteur pour gérer le changement d'URL serveur sans recréer le client Retrofit :
// HostSelectionInterceptor permet de changer l'hôte à la volée
class HostSelectionInterceptor : Interceptor {
@Volatile private var host: HttpUrl? = null
fun setHost(url: String) {
host = url.toHttpUrlOrNull()
}
override fun intercept(chain: Interceptor.Chain): Response {
val request = chain.request()
val newUrl = host?.let {
request.url.newBuilder()
.scheme(it.scheme)
.host(it.host)
.port(it.port)
.build()
} ?: request.url
return chain.proceed(request.newBuilder().url(newUrl).build())
}
}
Exécution des tests
# Tests unitaires
./gradlew test
# Tests instrumentés
./gradlew connectedAndroidTest
Build de release
-
Créer un keystore (si premier build)
keytool -genkey -v -keystore shaarit.keystore -alias shaarit \ -keyalg RSA -keysize 2048 -validity 10000 -
Créer
keystore.propertiesdans le répertoire racine :storeFile=shaarit.keystore storePassword=votre_password keyAlias=shaarit keyPassword=votre_password -
Compiler
./gradlew assembleRelease -
L'APK signé se trouve dans :
app/build/outputs/apk/release/app-release.apk
Dépendances principales
[versions]
agp = "8.13.2"
kotlin = "1.9.20"
hilt = "2.48.1"
retrofit = "2.9.0"
moshi = "1.15.0"
okhttp = "4.12.0"
paging = "3.2.1"
composeBom = "2023.08.00"
[libraries]
# Injection de dépendances
hilt-android = { module = "com.google.dagger:hilt-android", version.ref = "hilt" }
hilt-compiler = { module = "com.google.dagger:hilt-android-compiler", version.ref = "hilt" }
# Réseau
retrofit = { module = "com.squareup.retrofit2:retrofit", version.ref = "retrofit" }
retrofit-moshi = { module = "com.squareup.retrofit2:converter-moshi", version.ref = "retrofit" }
moshi = { module = "com.squareup.moshi:moshi", version.ref = "moshi" }
moshi-codegen = { module = "com.squareup.moshi:moshi-kotlin-codegen", version.ref = "moshi" }
okhttp-logging = { module = "com.squareup.okhttp3:logging-interceptor", version.ref = "okhttp" }
# Pagination
androidx-paging-runtime = { module = "androidx.paging:paging-runtime", version.ref = "paging" }
androidx-paging-compose = { module = "androidx.paging:paging-compose", version.ref = "paging" }
# Sécurité
androidx-security-crypto = { module = "androidx.security:security-crypto", version = "1.1.0-alpha06" }
Contribution
- Forker le projet
- Créer une branche feature (
git checkout -b feature/amazing-feature) - Committer vos changements (
git commit -m 'Add amazing feature') - Pusher sur la branche (
git push origin feature/amazing-feature) - Ouvrir une Pull Request
📄 Licence
Ce projet est sous licence MIT. Voir le fichier LICENSE pour plus de détails.
🙏 Remerciements
- Shaarli - Le gestionnaire de favoris auto-hébergé
- Jetpack Compose - UI toolkit moderne Android
- Material Design 3 - Système de design Google
📧 Contact
Pour toute question ou suggestion, n'hésitez pas à ouvrir une issue.