RÉSUMÉ
Le guide complet pour des applications offline-first en 2026
Découvrez les meilleures pratiques et technologies pour concevoir et développer des applications mobiles robustes qui fonctionnent parfaitement, même sans connexion internet.
Keywords: développement mobile, offline-first, synchronisation données
TABLE DES MATIÈRES
1. Contexte: L’Impératif du Offline-First en 2026
2. Architectures et Technologies Clés pour le Offline-First
3. Résolution de Problèmes: Défis Communs et Solutions Innovantes
4. Application Pratique: Mise en Œuvre d’une Application Offline-First
5. Conclusion: L’Avenir du Mobile est Hors Ligne
INTRODUCTION
1. Contexte: L’Impératif du Offline-First en 2026
Dans le paysage numérique de 2026, la connectivité n’est plus une garantie. Que ce soit en raison de zones blanches, de réseaux surchargés, de trajets en transport en commun ou de simples pannes de service, les utilisateurs mobiles s’attendent à ce que leurs applications fonctionnent de manière fluide et sans interruption. C’est ici qu’intervient le concept d’« offline-first », une approche de développement qui place l’expérience utilisateur hors ligne au cœur de la conception.
L’offline-first ne signifie pas simplement que l’application peut fonctionner sans internet ; cela implique une architecture où le stockage local est la source de vérité principale pour l’interface utilisateur, et où la synchronisation avec un serveur distant est une tâche asynchrone et secondaire. Cette philosophie améliore considérablement la résilience, la performance perçue et la fiabilité de l’application, transformant une contrainte technique en un avantage concurrentiel majeur.
« En 2026, une application mobile qui ne fonctionne pas hors ligne est une application qui échoue à répondre aux attentes fondamentales des utilisateurs. »
Pourquoi le Offline-First est-il crucial en 2026 ?
Les statistiques récentes soulignent l’importance croissante des applications offline-first. Une étude de l’UIT (Union internationale des télécommunications) de 2025 révélait que, malgré l’expansion de la 5G, près de 20% de la population mondiale n’avait pas d’accès internet fiable, et même dans les zones urbaines développées, les interruptions de service ou les latences élevées restent monnaie courante. Les utilisateurs passent en moyenne 4,5 heures par jour sur leurs appareils mobiles en 2026, et toute interruption due à un manque de connectivité peut entraîner frustration et désinstallation. Les applications offline-first garantissent une productivité ininterrompue, une meilleure accessibilité et une expérience utilisateur supérieure, peu importe les conditions du réseau.
POINT CLÉ
Le paradigme offline-first est une nécessité en 2026 pour toute application mobile visant la résilience, la performance et une satisfaction utilisateur optimale, en garantissant un accès continu aux fonctionnalités essentielles.
Avantages Clés de l’Approche Offline-First
Bénéfices Stratégiques
Fiabilité Accrue — L’application reste fonctionnelle même sans connexion, réduisant la frustration des utilisateurs et les points de défaillance liés au réseau.
Performance Optimisée — Les données étant stockées localement, les temps de chargement sont quasi instantanés, offrant une expérience utilisateur plus rapide et plus fluide que les requêtes réseau.
Réduction de la Consommation de Données — Moins de requêtes réseau signifie une consommation de données mobiles réduite, ce qui est un avantage économique pour l’utilisateur et écologique.
Amélioration de l’Expérience Utilisateur — Fluidité des interactions, feedback immédiat et sensation de contrôle total sur l’application, indépendamment de l’environnement.
Avantage Concurrentiel — Se démarquer sur un marché saturé en offrant une expérience utilisateur supérieure et plus robuste que les applications « online-only ».
ANALYSE DÉTAILLÉE
2. Architectures et Technologies Clés pour le Offline-First
La mise en œuvre d’une application offline-first repose sur plusieurs piliers technologiques et architecturaux. Il s’agit de choisir les bonnes bases de données locales, d’implémenter des stratégies de synchronisation robustes et de concevoir une interface utilisateur qui gère élégamment les différents états de connectivité.
2.1. Stockage Local Robuste
Le choix de la base de données locale est fondamental. Elle doit être performante, fiable et adaptée aux besoins spécifiques de l’application en termes de complexité des données, de volume et de fréquences d’accès. Voici les options les plus populaires en 2026 :
Options de Stockage Local
SQLite — La base de données relationnelle la plus répandue sur mobile. Elle est nativement supportée sur Android et peut être utilisée sur iOS (via Core Data ou des wrappers). Idéale pour les données structurées et les requêtes complexes. Nécessite une gestion manuelle de la migration et des schémas.
Realm Database — Une base de données NoSQL mobile-first, conçue pour la performance et la facilité d’utilisation. Disponible pour iOS, Android, et React Native. Offre des requêtes en temps réel et une API simple. Particulièrement efficace pour les données non-relationnelles et les objets complexes.
Core Data (iOS/macOS) — Le framework de persistance objet d’Apple. Permet de gérer des graphes d’objets et de persister les données sur SQLite, binaire ou XML. Très intégré à l’écosystème Apple, mais avec une courbe d’apprentissage. Offre des fonctionnalités avancées comme les requêtes prédictives et la gestion des versions.
Room Persistence Library (Android) — Une surcouche d’abstraction au-dessus de SQLite, faisant partie des Android Jetpack libraries. Facilite l’utilisation de SQLite avec des annotations pour définir les entités, les DAOs (Data Access Objects) et les bases de données. Offre une vérification du temps de compilation et une meilleure intégration avec les composants Android.
IndexedDB / LocalStorage (PWA) — Pour les Progressive Web Apps (PWA), IndexedDB est une base de données de documents côté client, idéale pour des volumes de données importants et des recherches complexes. LocalStorage est plus simple mais limité en taille et synchrone, à réserver pour de petites quantités de données clé-valeur.

Voici un tableau comparatif pour vous aider à choisir la bonne solution de stockage :
Tableau Comparatif des Bases de Données Mobiles Locales (2026)
| Base de Données | Type | Plateformes | Facilité d’Usage | Performance | Cas d’Usage Idéal |
|---|---|---|---|---|---|
| SQLite | Relationnel | Android, iOS (via wrappers), PWA (WebSQL déprécié mais utilisable pour certaines migrations) | Moyenne (SQL direct) | Très bonne | Données structurées, relations complexes, rapports |
| Realm Database | NoSQL (Objet) | iOS, Android, React Native, Xamarin, PWA (via Realm Web) | Élevée (API objet) | Excellente (temps réel) | Données non-relationnelles, synchronisation en temps réel, applications collaboratives |
| Core Data | Objet (ORM) | iOS, macOS, watchOS, tvOS | Moyenne (courbe d’apprentissage) | Très bonne | Applications Apple natives, gestion d’objets complexes, intégration OS |
| Room | Relationnel (ORM) | Android | Élevée (API Jetpack) | Très bonne | Applications Android natives, intégration Jetpack, données structurées |
| IndexedDB | NoSQL (Clé-Valeur) | PWA (navigateurs web) | Moyenne (API asynchrone) | Bonne | Applications PWA, stockage de données structurées côté client |
POINT CLÉ
Le choix de la base de données locale doit être guidé par la complexité des données, les plateformes cibles, la performance requise et la facilité d’intégration avec le reste de l’architecture de l’application.
2.2. Stratégies de Synchronisation des Données
La synchronisation des données est le cœur battant de toute application offline-first. Elle détermine comment les modifications locales sont envoyées au serveur et comment les données du serveur sont mises à jour localement, tout en gérant les éventuels conflits.
Il existe plusieurs approches, chacune avec ses avantages et inconvénients :
Types de Synchronisation
Synchronisation Bidirectionnelle (Two-way Sync) — La plus complexe mais la plus complète. Les modifications peuvent être faites à la fois côté client et côté serveur, et sont fusionnées. Nécessite une gestion robuste des conflits. C’est le modèle le plus courant pour les applications collaboratives.
Synchronisation Unidirectionnelle (One-way Sync) —
- Client-to-Server (Push) : Le client envoie ses modifications au serveur. Moins complexe, mais le client ne reçoit pas les mises à jour du serveur en temps réel. Utile pour les applications de collecte de données.
- Server-to-Client (Pull) : Le client récupère les données du serveur. Typique pour les applications de lecture intensive ou les flux d’actualités.
Synchronisation Delta — Au lieu d’envoyer toutes les données, seules les modifications (différences ou « deltas ») sont échangées. Cela réduit considérablement la bande passante et la latence, mais nécessite une logique de suivi des modifications plus sophistiquée (timestamps, numéros de version).

Pour implémenter ces stratégies, diverses techniques peuvent être employées :
Techniques de Synchronisation
File d’attente de Modifications (Operation Queue) — Toutes les opérations effectuées hors ligne sont enregistrées dans une file d’attente locale (souvent dans la base de données). Lorsque la connectivité est rétablie, l’application parcourt cette file et envoie les opérations au serveur dans l’ordre.
Timestamps et Versioning — Chaque enregistrement de données, côté client et côté serveur, est estampillé avec un horodatage de dernière modification ou un numéro de version. Lors de la synchronisation, ces métadonnées sont utilisées pour identifier les modifications et résoudre les conflits (par exemple, « last-write wins »).
WebSockets et Événements — Pour une synchronisation quasi en temps réel, les WebSockets peuvent être utilisés pour que le serveur « pousse » les mises à jour aux clients connectés dès qu’elles se produisent, complétant ainsi les mécanismes de pull pour les clients hors ligne.
Service Workers (PWA) — Pour les PWA, les Service Workers agissent comme un proxy programmable entre le navigateur et le réseau, permettant une gestion fine de la mise en cache et de la synchronisation en arrière-plan.
Plateformes BaaS (Backend as a Service) — Des solutions comme Firebase Firestore ou AWS AppSync offrent des fonctionnalités offline-first intégrées, avec gestion de la synchronisation et résolution de conflits souvent prêtes à l’emploi, réduisant considérablement la complexité de développement.
2.3. Gestion de l’État et UI/UX Offline
Une application offline-first doit également offrir une expérience utilisateur cohérente, quel que soit l’état de la connexion. Cela implique une conception UI/UX spécifique :
Principes UI/UX Offline-First
Feedback Visuel Clair — Les utilisateurs doivent toujours savoir si l’application est en ligne, hors ligne, ou en cours de synchronisation. Des indicateurs visuels (icônes, barres de statut) sont essentiels. Par exemple, une petite icône de nuage barré pour le mode hors ligne, ou une barre de progression pour la synchronisation.
Actions Différées — Les actions effectuées hors ligne doivent être visuellement marquées comme « en attente » ou « en cours de synchronisation ». L’utilisateur doit comprendre que l’action sera finalisée une fois la connexion rétablie.
Gestion des Erreurs et des Conflits — En cas d’échec de synchronisation ou de conflit, des messages clairs et des options de résolution (par exemple, « conserver ma version », « ignorer », « voir les différences ») doivent être présentés à l’utilisateur.
Mise en Cache des Ressources — Les images, vidéos et autres assets doivent être mis en cache localement pour garantir une expérience utilisateur complète, même sans connexion. Les Service Workers sont excellents pour cela dans les PWA, tandis que les frameworks natifs offrent des solutions de mise en cache pour les images.
Optimisation des Requêtes — Les données affichées doivent être chargées rapidement depuis le cache local. Les requêtes coûteuses au réseau doivent être minimisées ou effectuées en arrière-plan.
RÉSOLUTION DE PROBLÈMES
3. Résolution de Problèmes: Défis Communs et Solutions Innovantes
Développer une application offline-first présente son lot de défis techniques. La gestion des conflits de données, la sécurité du stockage local et l’optimisation des performances sont des aspects critiques à aborder avec rigueur.
3.1. Gestion des Conflits de Données
Les conflits surviennent lorsqu’une même donnée est modifiée simultanément par le client hors ligne et par une autre source (un autre client ou le serveur). La résolution des conflits est l’un des aspects les plus complexes du développement offline-first.
PROBLÈME 01
Conflits de Synchronisation
Deux versions différentes d’un même enregistrement de données existent sur le client et le serveur (ou entre deux clients), créant une incohérence lors de la tentative de synchronisation.
SOLUTION — Stratégies de Résolution de Conflits
Plusieurs stratégies peuvent être adoptées, en fonction de la criticité des données et de l’expérience utilisateur souhaitée :
- Last-Write Wins (LWW) : La version la plus récente (basée sur l’horodatage) l’emporte. Simple à implémenter, mais peut entraîner des pertes de données si l’horodatage n’est pas fiable ou si une modification plus ancienne mais importante est écrasée.
- Client-Wins / Server-Wins : Une des versions est toujours privilégiée. Par exemple, les modifications du client l’emportent toujours (utile pour les applications de prise de notes) ou le serveur est toujours la source de vérité.
- Fusion Sémantique (Merge Logic) : Cette approche tente de fusionner intelligemment les modifications. Par exemple, si deux utilisateurs ajoutent des éléments différents à une liste, les deux ajouts sont conservés. Nécessite une logique métier complexe.
- Notification Utilisateur : L’utilisateur est informé du conflit et invité à choisir la version à conserver ou à fusionner manuellement. C’est l’approche la plus sûre mais potentiellement intrusive.
Voici un exemple simplifié de logique LWW avec des horodatages:
EXPLICATION DU CODE
Ce pseudocode illustre une fonction de résolution de conflit simple basée sur le principe du « dernier écrit l’emporte ». Il compare les horodatages de dernière modification entre les données locales et les données du serveur pour décider quelle version est la plus récente.
fonction resoudreConflit(donneesLocales, donneesServeur):
si donneesLocales.derniereModification > donneesServeur.derniereModification:
retourner donneesLocales // La version locale est plus récente
sinon si donneesServeur.derniereModification > donneesLocales.derniereModification:
retourner donneesServeur // La version serveur est plus récente
sinon:
// Les horodatages sont identiques ou les données sont identiques
// Peut nécessiter une fusion sémantique ou une décision par défaut
retourner donneesServeur // Par défaut, la version serveur l'emporte
POINT CLÉ
La gestion des conflits est un point critique. Une stratégie claire doit être définie dès le début du projet, en considérant la nature des données et les attentes des utilisateurs. Les horodatages et les numéros de version sont des outils essentiels.
3.2. Sécurité des Données Hors Ligne
Stocker des données sensibles localement expose l’application à des risques de sécurité. Il est impératif de protéger ces informations contre les accès non autorisés, surtout si l’appareil est perdu ou volé.
PROBLÈME 02
Exposition des Données Locales
Les données stockées localement peuvent être vulnérables si l’appareil est compromis ou si l’application n’est pas correctement sécurisée, entraînant des fuites d’informations personnelles ou sensibles.
SOLUTION — Mesures de Sécurité Robustes
La sécurité offline-first repose sur plusieurs couches de protection :
- Chiffrement des Données : Toutes les données sensibles doivent être chiffrées avant d’être stockées localement. Des algorithmes comme AES-256 sont recommandés. La plupart des bases de données mobiles (Realm, SQLCipher pour SQLite) offrent des options de chiffrement intégrées.
- Stockage Sécurisé des Clés : Les clés de chiffrement ne doivent jamais être stockées en clair dans l’application. Utilisez le Keystore d’Android ou le Keychain d’iOS pour stocker ces clés en toute sécurité.
- Authentification Robuste : Pour les applications avec des données hautement sensibles, envisagez une ré-authentification de l’utilisateur (via biométrie ou code PIN) avant d’accéder à certaines sections de l’application, même hors ligne.
- Gestion des Sessions : Les tokens d’authentification doivent avoir une durée de vie limitée et être invalidés à distance si un appareil est compromis.
- Obfuscation du Code : Rendre la rétro-ingénierie plus difficile en obfuscant le code de l’application.
La mise en œuvre du chiffrement pour une base de données Realm en Kotlin pourrait ressembler à ceci :
EXPLICATION DU CODE
Cet exemple Kotlin montre comment configurer une base de données Realm chiffrée. La clé de chiffrement doit être générée une seule fois et stockée de manière sécurisée (par exemple, dans le Keystore Android) pour être réutilisée lors des accès ultérieurs.
// Exemple Kotlin pour Realm avec chiffrement
import io.realm.Realm
import io.realm.RealmConfiguration
import java.security.SecureRandom
// Générer une clé de chiffrement (à faire une seule fois et à stocker sécuritairement)
fun generateRealmKey(): ByteArray {
val key = ByteArray(64)
SecureRandom().nextBytes(key)
return key
}
// Récupérer la clé stockée (exemple simplifié, utiliser Keystore en production)
fun getStoredRealmKey(): ByteArray {
// En production, cette clé serait récupérée du Keystore Android ou Keychain iOS
// Pour l'exemple, nous allons simuler une clé
return generateRealmKey() // Ne pas faire cela en production!
}
fun configureRealmWithEncryption() {
Realm.init(applicationContext) // Initialiser Realm une fois au démarrage de l'app
val encryptionKey = getStoredRealmKey()
val config = RealmConfiguration.Builder()
.name("encrypted.realm") // Nom du fichier de la base de données
.encryptionKey(encryptionKey) // Appliquer la clé de chiffrement
.schemaVersion(1) // Version du schéma de la base de données
.deleteRealmIfMigrationNeeded() // Seulement pour le développement, à éviter en production
.build()
Realm.setDefaultConfiguration(config)
// Vous pouvez maintenant obtenir une instance de Realm chiffrée
val realm = Realm.getDefaultInstance()
// ... utiliser Realm ...
realm.close()
}

3.3. Performance et Consommation Énergétique
Une synchronisation fréquente ou mal optimisée peut épuiser la batterie et consommer des ressources système précieuses. L’équilibre entre la fraîcheur des données et l’efficience est délicat.
PROBLÈME 03
Drainage de la Batterie et Surcharge Réseau
Des opérations de synchronisation trop fréquentes, le transfert de gros volumes de données ou des requêtes non optimisées peuvent entraîner une consommation excessive de batterie et une utilisation inefficace de la bande passante, nuisant à l’expérience utilisateur globale.
SOLUTION — Optimisation de la Synchronisation
Pour garantir une application performante et économe en énergie :
- Synchronisation Conditionnelle : Ne synchronisez que lorsque la connectivité est stable (Wi-Fi de préférence), lorsque l’appareil est en charge, ou lorsque l’application est en arrière-plan et que les ressources sont disponibles. Utilisez les APIs de planification de tâches du système d’exploitation (WorkManager sur Android, BackgroundTasks sur iOS).
- Synchronisation Delta et Compression : Envoyez uniquement les modifications (différences) et compressez les données pour réduire la taille des transferts.
- Déduplication des Données : Assurez-vous que les mêmes données ne sont pas téléchargées ou envoyées plusieurs fois.
- Batching des Opérations : Regroupez plusieurs petites modifications en une seule requête pour réduire le nombre de connexions réseau.
- Stratégies de Rétroaction : Implémentez des mécanismes de « backoff » exponentiel pour les tentatives de synchronisation échouées afin de ne pas surcharger le réseau ou le serveur.
Les APIs modernes comme WorkManager pour Android offrent des moyens efficaces de planifier des tâches de synchronisation :
EXPLICATION DU CODE
Cet exemple Kotlin utilise WorkManager pour planifier une tâche de synchronisation qui s’exécutera uniquement lorsque l’appareil est connecté à un réseau non mesuré (par exemple, Wi-Fi) et qu’il est en charge, optimisant ainsi la consommation d’énergie et de données.
// Exemple Kotlin pour planifier une tâche de synchronisation avec WorkManager (Android)
import androidx.work.*
import java.util.concurrent.TimeUnit
class SyncWorker(appContext: Context, workerParams: WorkerParameters) : Worker(appContext, workerParams) {
override fun doWork(): Result {
// Logique de synchronisation réelle ici
Log.d("SyncWorker", "Début de la synchronisation des données...")
// ... effectuer les requêtes réseau et les mises à jour de la base de données locale ...
Log.d("SyncWorker", "Synchronisation terminée.")
return Result.success() // Ou Result.retry() en cas d'échec temporaire
}
}
fun scheduleSyncTask(context: Context) {
val constraints = Constraints.Builder()
.setRequiredNetworkType(NetworkType.UNMETERED) // Nécessite un réseau non mesuré (ex: Wi-Fi)
.setRequiresBatteryNotLow(true) // Ne pas s'exécuter si la batterie est faible
.setRequiresCharging(true) // S'exécuter uniquement si l'appareil est en charge
.build()
val syncRequest = PeriodicWorkRequestBuilder(
15, TimeUnit.MINUTES // Répéter toutes les 15 minutes (minimum)
)
.setConstraints(constraints)
.setBackoffCriteria(
BackoffPolicy.EXPONENTIAL, // Politique de réessai exponentielle
10, TimeUnit.SECONDS // Attendre 10 secondes avant le premier réessai
)
.build()
WorkManager.getInstance(context).enqueueUniquePeriodicWork(
"DataSyncWork", // Nom unique pour cette tâche
ExistingPeriodicWorkPolicy.KEEP, // Conserver la tâche existante si déjà planifiée
syncRequest
)
}
CAS PRATIQUE
4. Application Pratique: Mise en Œuvre d’une Application Offline-First
Pour mieux illustrer les concepts abordés, prenons l’exemple d’une application de gestion de tâches (To-Do List) qui doit fonctionner parfaitement hors ligne.
4.1. Cas d’Usage: Application de Gestion de Tâches
Titre du Cas: Kwontenu To-Do
Permettre aux utilisateurs de créer, modifier, marquer comme terminées et supprimer des tâches, même sans connexion internet. Toutes les modifications doivent être synchronisées avec le serveur dès que la connexion est rétablie.

4.2. Workflow Détaillé d’Implémentation
Voici les étapes clés pour construire cette application offline-first :
1
Initialisation du Stockage Local
Au premier lancement de l’application, initialiser une base de données locale (par exemple, Room pour Android, Core Data pour iOS, ou Realm pour les deux). Définir le schéma des tâches avec des champs comme id, titre, description, estTerminee, derniereModification, et un champ statutSync (par exemple, ‘pending’, ‘synced’, ‘deleted’).
2
Récupération Initiale des Données
Lors de la première connexion ou après une réinstallation, l’application télécharge toutes les tâches de l’utilisateur depuis le serveur et les stocke dans la base de données locale. Chaque tâche reçoit un id unique (généré par le serveur), un derniereModification et son statutSync est ‘synced’.
3
Opérations CRUD Hors Ligne
Toutes les opérations (Créer, Lire, Mettre à jour, Supprimer) s’effectuent d’abord sur la base de données locale. Si une tâche est créée, son id peut être un UUID temporaire généré localement, et son statutSync est mis à ‘pending’. Les modifications et suppressions mettent à jour le derniereModification et le statutSync.
4
Détection de la Connectivité et Synchronisation
L’application surveille l’état de la connexion réseau. Dès qu’une connexion est détectée, un processus de synchronisation en arrière-plan est déclenché (par exemple, via WorkManager ou BackgroundTasks). Ce processus envoie toutes les modifications en attente (‘pending’) au serveur et récupère les mises à jour depuis le serveur.
5
Gestion des Erreurs et des Conflits
Pendant la synchronisation, si le serveur renvoie une erreur ou détecte un conflit (par exemple, une tâche a été modifiée à la fois localement et sur le serveur), la logique de résolution de conflit est appliquée. Si un conflit ne peut pas être résolu automatiquement (par exemple, « last-write wins »), l’utilisateur est notifié et peut être invité à intervenir.
6
Mise à Jour de l’UI
Une fois la synchronisation réussie, l’UI est mise à jour pour refléter les données du serveur. Les tâches dont le statutSync était ‘pending’ passent à ‘synced’. Les tâches supprimées sont retirées de la base de données locale. Les indicateurs de statut de connexion et de synchronisation sont mis à jour.
POINT CLÉ
L’implémentation d’une application offline-first nécessite une gestion minutieuse de l’état des données locales et un mécanisme de synchronisation asynchrone qui gère la détection de connectivité, les envois (push) et les réceptions (pull) de données, ainsi que la résolution des conflits.
4.3. Exemple de Code: Logique de Synchronisation Simplifiée
Voici un pseudocode illustrant la logique principale d’un processus de synchronisation pour une tâche :
EXPLICATION DU CODE
Cette fonction de synchronisation simule les étapes d’envoi des modifications locales au serveur et de récupération des mises à jour du serveur. Elle gère les tâches nouvelles, modifiées et supprimées localement, et résout les conflits en utilisant une stratégie « last-write wins ».
// Pseudocode pour la logique de synchronisation d'une application de tâches
fonction synchroniserTaches():
si pas_de_connexion_internet():
afficher_message("Pas de connexion internet. Synchronisation différée.")
retourner
afficher_message("Synchronisation en cours...")
// Étape 1: Envoyer les modifications locales au serveur
tachesEnAttente = obtenir_taches_locales_par_statut("pending")
pour chaque tache dans tachesEnAttente:
si tache.id_serveur est null: // Nouvelle tâche
reponse = api.creerTache(tache)
si reponse.succes:
mettre_a_jour_tache_locale(tache.id_local, { id_serveur: reponse.id, statutSync: "synced", derniereModification: reponse.timestamp })
sinon:
gerer_erreur_serveur(reponse.erreur)
sinon: // Tâche modifiée
reponse = api.mettreAJourTache(tache.id_serveur, tache)
si reponse.succes:
mettre_a_jour_tache_locale(tache.id_local, { statutSync: "synced", derniereModification: reponse.timestamp })
sinon:
gerer_erreur_serveur(reponse.erreur)
tachesSupprimeesEnAttente = obtenir_taches_locales_par_statut("deleted")
pour chaque tache dans tachesSupprimeesEnAttente:
reponse = api.supprimerTache(tache.id_serveur)
si reponse.succes:
supprimer_tache_locale(tache.id_local)
sinon:
gerer_erreur_serveur(reponse.erreur)
// Étape 2: Récupérer les mises à jour depuis le serveur
derniereSyncTimestamp = obtenir_dernier_timestamp_sync()
misesAJourServeur = api.obtenirMisesAJourDepuis(derniereSyncTimestamp)
pour chaque majServeur dans misesAJourServeur:
tacheLocale = obtenir_tache_locale_par_id_serveur(majServeur.id)
si tacheLocale est null: // Nouvelle tâche du serveur
ajouter_tache_locale(majServeur, { statutSync: "synced" })
sinon si majServeur.estSupprime: // Tâche supprimée sur le serveur
supprimer_tache_locale(tacheLocale.id_local)
sinon: // Tâche modifiée, gérer les conflits
si majServeur.derniereModification > tacheLocale.derniereModification:
mettre_a_jour_tache_locale(tacheLocale.id_local, majServeur, { statutSync: "synced" })
sinon si tacheLocale.derniereModification > majServeur.derniereModification:
// La version locale est plus récente, la modification locale sera envoyée lors de la prochaine sync (déjà fait si statut "pending")
// Assurez-vous que la tâche locale est marquée comme "pending" si elle n'a pas encore été poussée
si tacheLocale.statutSync != "pending":
mettre_a_jour_tache_locale(tacheLocale.id_local, { statutSync: "pending" })
sinon:
// Versions identiques ou pas de conflit, marquer comme synchronisé
mettre_a_jour_tache_locale(tacheLocale.id_local, { statutSync: "synced" })
mettre_a_jour_dernier_timestamp_sync(maintenant())
afficher_message("Synchronisation terminée avec succès.")
rafraichir_ui_taches()
CONCLUSION