Bruno Charest a9475c16b1 feat: Update Gradle wrapper to version 8.13
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
2026-01-28 11:38:49 -05:00
2026-01-11 19:47:49 -05:00
2026-01-11 19:47:49 -05:00
2026-01-11 19:47:49 -05:00
2026-01-11 19:47:49 -05:00
2026-01-11 19:47:49 -05:00
2026-01-11 19:47:49 -05:00

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.

Tech Stack Android Jetpack Compose License


📱 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
  1. JDK 17 (ou plus récent) installé
  2. Android SDK installé (Platform API 34)
  3. Gradle 8.0+ (si gradlew est manquant)
Étapes de compilation
  1. Cloner le repository

    git clone https://github.com/votre-username/ShaarIt.git
    cd ShaarIt
    
  2. Configurer l'emplacement du SDK Android

    Si la variable ANDROID_HOME n'est pas définie, créez un fichier local.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
    
  3. Compiler l'APK Debug

    # Windows
    ./gradlew assembleDebug
    
    # Linux/macOS
    chmod +x gradlew
    ./gradlew assembleDebug
    
  4. L'APK se trouve dans : app/build/outputs/apk/debug/app-debug.apk

  5. Installer sur l'appareil

    adb install -r app/build/outputs/apk/debug/app-debug.apk
    

Configuration initiale de l'app

  1. Ouvrez l'application ShaarIt
  2. Entrez l'URL de votre instance Shaarli (ex: https://monserveur.com/shaarli)
  3. Entrez votre Secret API (trouvé dans les paramètres admin de Shaarli)
  4. 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

  1. Créer un keystore (si premier build)

    keytool -genkey -v -keystore shaarit.keystore -alias shaarit \
            -keyalg RSA -keysize 2048 -validity 10000
    
  2. Créer keystore.properties dans le répertoire racine :

    storeFile=shaarit.keystore
    storePassword=votre_password
    keyAlias=shaarit
    keyPassword=votre_password
    
  3. Compiler

    ./gradlew assembleRelease
    
  4. 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

  1. Forker le projet
  2. Créer une branche feature (git checkout -b feature/amazing-feature)
  3. Committer vos changements (git commit -m 'Add amazing feature')
  4. Pusher sur la branche (git push origin feature/amazing-feature)
  5. Ouvrir une Pull Request

📄 Licence

Ce projet est sous licence MIT. Voir le fichier LICENSE pour plus de détails.


🙏 Remerciements


📧 Contact

Pour toute question ou suggestion, n'hésitez pas à ouvrir une issue.

Description
Sharrit - Android app to view, manage and share URL from Shaari application.
Readme 1.2 MiB
Languages
Kotlin 97.3%
Python 2%
PowerShell 0.7%