VSCode Extension: Achievements
- POK
- 2024-2025
- temps 2
- dev
- vscode
- Loïck Goupil-Hallay
Développement d'une extension permettant de débloquer des succès en fonction de l'utilisation de VSCode.
POK avancé
Achievements
Introduction
Toujours dans l'optique de créer le meilleur environnement de développement possible, je me suis demandé ce qui permet au développeur d'être le plus heureux quand il travaille. C'est alors que je me suis rappelé que la majorité des développeurs a un passif (ou un présent) de joueur de jeux vidéo. Un système de succès pousse les joueurs à continuer de jouer et les récompense pour leur temps passé sur le jeu. Cela booste la motivation et la satisfaction du joueur.
Et puis Qui n'a jamais rêvé de terminer VSCode ? C'est pourquoi j'ai décidé de développer une extension pour VSCode permettant de débloquer des achievements en fonction de l'utilisation de l'éditeur.
Il existe déjà deux extensions de ce type sur le marché, mais elles ne sont pas complètes du tout et ne sont plus maintenues. J'ai donc décidé de développer la mienne, qui sera plus complète et plus à jour.
Fonctionnement
L'extension Achievements fonctionne de manière assez simple. Le but est de ne pas impacter les performances de l'éditeur et de pouvoir fonctionner hors ligne.
Workflow
Le workflow de l'extension est le suivant:
- L'intégrité de la base de données est vérifiée à chaque démarrage de l'extension. S'il y a un problème, elle est patchée comme il faut.
- Des listeners sont mis en place pour écouter les événements de l'éditeur (ouverture de fichier, sauvegarde, etc.).
- Chaque listener déclenche l'augmentation d'un ou plusieurs critère de progression.
- Lorsqu'une progression est augmentée, on vérifie si elle permet de débloquer un succès.
- Si un succès est débloqué, on le notifie à l'utilisateur.
- A tout moment, l'utilisateur peut aller consulter la liste des succès débloqués / en cours sur la Webview de l'extension.
Webview
L'extension dispose d'une Webview qui permet à l'utilisateur de consulter la liste des succès débloqués et en cours. Cela permet de garder un historique des succès débloqués et de voir les succès restants à débloquer.

Commandes
L'extension ajoute des commandes custom à la palette VSCode à vscode:

achievements.enable: Active / désactive l'extensionachievements.settings: Ouvre la configuration de l'extensionachievements.show: Ouvre la Webview des succès
Il s'agit de raccourcis pour les actions les plus courantes.
Settings
L'extension dispose de quelques paramètres de configuration:
achievements.enabled: Active / désactive l'extensionachievements.logLevel: Niveau de log de l'extensionachievements.logDirectory: Dossier de stockage des logsachievements.username: Nom d'utilisateur à afficher dans la Webviewachievements.listeners.debug: Active / désactive les listeners pour les évènements de type debug / breakpointachievements.listeners.extensions: Active / désactive les listeners pour les évènements de type extension, thèmeachievements.listeners.files: Active / désactive les listeners pour les évènements de type ouverture de fichier, sauvegardeachievements.listeners.git: Active / désactive les listeners pour les évènements de type gitachievements.listeners.tabs: Active / désactive les listeners pour les évènements de type ouverture de tabachievements.listeners.tasks: Active / désactive les listeners pour les évènements de type tâches VSCodeachievements.listeners.time: Active / désactive les listeners pour les évènements de type temps passé
Base de données
- J'utilise une base de données SQLite pour stocker les succès, leurs conditions de déblocage, leur état, la date de complétion, et tout un tas de propriétés.
- Je stocke aussi la progression de chaque critère pour débloquer les succès. Cela me permet de savoir si un succès est débloqué ou non.
- Il y a de nombreux achievements qui ne peuvent se débloquer que si certains autres sont débloqués. Pour cela, j'utilise une table qui stocke les dépendances entre les succès.
- Enfin, je stocke les versions de la base de données pour pouvoir mettre à jour les tables en fonction de la version de l'extension. (C'est utile pour les mises à jour qui vont nécessiter des migrations de bases de données).
erDiagram
SchemaVersion {
int id PK
int version
datetime applied_at
}
Achievement {
int id PK
string title
string icon
string category
string group
string description
int tier
int exp
int hidden
int repeatable
boolean achieved
datetime achievedAt
}
AchievementLabel {
int achievement_id FK
string label
}
AchievementCriteria {
int id PK
int achievement_id FK
int progression_id FK
string required_value
string type
string comparison_operator
}
AchievementRequirement {
int achievement_id FK
int requirement_id FK
}
Progression {
int id PK
string name
string type
string value
}
DailySession {
int id PK
string date
int duration
}
Achievement ||--o{ AchievementLabel : "has"
Achievement ||--|{ AchievementCriteria : "has"
Achievement ||--o{ AchievementRequirement : "has"
AchievementRequirement ||--|| Achievement : "references"
AchievementCriteria }|--|{ Progression : "references"
Développement
VSCode fonctionne grâce à Electron, ce qui signifie qu'il fonctionne exactement comme un site web. Le développement des extensions se fait donc en JavaScript / TypeScript. J'ai choisi d'utiliser TypeScript pour mon extension car il permet de s'assurer que le code est correctement typé avant de l'exécuter. Cela permet de réduire les erreurs et de gagner du temps.
Le développement se centre sur l'optimisation des performances et la réduction de l'impact sur l'éditeur. Cela passe par deux choses essentielles:
- l'optimisation SQL pour réduire le nombre de requêtes et traiter les données le plus rapidement possible
- la gestion des listeners pour ne pas surcharger l'éditeur avec des événements inutiles ou dupliquer les fonctionnalités déjà existantes
Dépendances
Pour mon extension, j'ai utilisé les dépendances suivantes :
- Développement
npmpour le management des dépendancesesbuildpour le bundling du code (le lint, la compilation de TypeScript)eslintpour l'analyse statique du codetypescriptpour le typage du code
- Run
vscodepour l'API de VSCodebetter-sqlite3pour la base de donnéesreactpour l'interface utilisateurstyled-componentspour les styles de l'interface des composants react
Post-mortem
La documentation de l'API de VSCode concernant les webviews est TRES MAUVAISE, contrairement à ce qu'on pourrait croire, il est très difficile de trouver des exemples concrets pour réaliser des actions relativement peu complexes. On dirait que les développeurs de VSCode ont oublié de documenter leur propre API.
Au niveau de l'extensibilité, qui est un des arguments principaux de VSCode, c'est un peu la déception. Il est très difficile de faire des choses qui sortent de l'ordinaire concernant les webviews. Je suis obligé de passer par de multiples hacks pour arriver à mes fins (afficher des images ?????). La communication extension <-> webview est un véritable calvaire avec 0 documentation mis à par un exemple miteux. Le framework n'est vraiment pas bon pour le développement de vues personnalisées et complexes (ils déconseillent aux utilisateurs de développer des webviews pour des raisons de performances mais ce n'est pas une raison pour ne pas prendre en charge leur ajout).
Le bundle des vues n'est pas prévu par défaut par VSCode, c'est une catastrophe pour packager ses images / icones / css / js. Il faut tout mettre à la main dans le bundle, ce qui est une perte de temps et d'énergie pour des choses qui devraient être automatisées.
Planning
| Date | Heures passées | Indications |
|---|---|---|
| Mercredi 12/11 | 3H | Etablissement du projet, création du premier modèle de base de données |
| Jeudi 13/11 | 4H | Création des premiers succès (1200), standardisation de l'attribution des points, des difficultés,... |
| Samedi 15/11 | 3H | Création de la webview et communication extension <-> webview |
| Samedi 01/12 | 6H | Migration / Optimisation SQL pour minimiser l'impact sur les performances |
| Samedi 08/12 | 4H | Création des listeners d'events et tests d'intégration |