diff --git a/.portfolio/diagrams/diagram.svg b/.portfolio/diagrams/diagram.svg new file mode 100644 index 0000000..4473fa4 --- /dev/null +++ b/.portfolio/diagrams/diagram.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/.portfolio/portfolio.md b/.portfolio/portfolio.md new file mode 100644 index 0000000..b8034ec --- /dev/null +++ b/.portfolio/portfolio.md @@ -0,0 +1,419 @@ +--- +title: "ReadRSS" +description: "Application de bureau (Rust) pour lire les flux RSS. Interface graphique rapide et minimale." +date: "2025-10-29" +tags: ["rust","gui","rss","desktop","egui"] +lang: "fr" + +# Configuration techStack +techStack: + - name: "Rust" + category: "language" + icon: "🦀" + - name: "egui / eframe" + category: "framework" + icon: "🖼️" + - name: "tokio" + category: "tool" + icon: "⚡" + - name: "feed-rs" + category: "tool" + icon: "📡" + - name: "ureq" + category: "tool" + icon: "🌐" + - name: "serde" + category: "tool" + icon: "💾" + - name: "Shell" + category: "language" + icon: "($(curl -s https://emojicdn.elk.sh/:-shell-?style=twitter | jq -r .em | head -n 1))" + +# Architecture du projet +architecture: + overview: "L'application suit une architecture 'headless' claire, séparant la logique métier de l'interface. Le crate `rss-core` gère toute la logique : le fetching HTTP asynchrone (via tokio et ureq), le parsing des flux (feed-rs), et la gestion de la base de données (fichiers JSON via serde). Le crate `rss-gui` est un consommateur de cette logique, se concentrant uniquement sur le rendu de l'interface graphique avec `egui` et la gestion des états de la vue." + components: + - "rss-core (Bibliothèque Rust) : Crate 'backend' indépendant (lib.rs). Il gère la structure des données (Feed, Article), la persistence (lecture/écriture JSON via serde), et expose les fonctions publiques (ex: add_feed, fetch_articles)." + - "rss-gui (Exécutable Rust) : Crate 'frontend' qui utilise eframe pour créer la fenêtre de bureau. Il implémente le trait eframe::App pour gérer le cycle de vie de l'application et le rendu." + - "tokio (Runtime Asynchrone) : Composant essentiel dans `rss-core`. Permet au `fetcher` de télécharger les flux RSS de manière non-bloquante, évitant de geler l'application." + - "feed-rs (Parseur de flux) : La bibliothèque qui transforme le texte XML brut (récupéré par ureq) en structures Rust (feed_rs::model::Feed) faciles à manipuler." + - "Gestionnaire d'état (GuiState) : La structure principale dans `rss-gui` qui contient l'état de l'interface (flux sélectionné, article sélectionné, onglet actif) et les données (rss_core::Rss)." + +# Diagrammes d'architecture (optionnel) +diagrams: + - path: "https://raw.githubusercontent.com/xAMA0x/ReadRSS/main/.portfolio/diagrams/readrss-architecture.svg" + title: "Architecture Core / GUI" + description: "Vue d'ensemble de la séparation des crates (logique et interface)" + +# URLs et liens +demo_url: "" +demo_label: "" +github_url: "https://github.com/xAMA0x/ReadRSS" +--- + +## 🎯 Vue d'ensemble + +
+ ReadRSS est un lecteur de flux RSS natif et minimaliste pour le bureau. Développé en Rust avec egui, il se concentre sur la rapidité et la simplicité, sans fioritures inutiles. Il gère l'ajout, le rafraîchissement et la lecture de vos flux en local, avec une interface réactive qui démarre instantanément.
+
+ Répondre au sujet imposé de la matière "Rust" à l'ESGI. L'objectif premier était de livrer un projet fonctionnel pour l'examen. +
+
+ Mettre en pratique l'ownership, le borrowing, la gestion des crates (core/gui), et la gestion d'erreurs (`Result
+ Découvrir et utiliser un framework de GUI Rust (comme `egui`) pour créer une application de bureau multiplateforme réactive. +
++ Implémenter des opérations réseau (fetching RSS) non-bloquantes en utilisant un runtime asynchrone (`tokio`) pour ne pas geler l'interface. +
++ Travailler en équipe sur un dépôt Git partagé, gérer la séparation des modules (`rss-core`, `rss-gui`) et les dépendances `Cargo.toml`. +
+
+ Le projet est construit sur une architecture "headless" propre à Rust, séparant la logique métier (Core) de la présentation (GUI). Le crate rss-core est une bibliothèque (lib.rs) qui ne sait rien de l'interface, tandis que rss-gui est un binaire (main.rs) qui importe rss-core comme une simple dépendance.
+
rss-core (Bibliothèque / Backend) : Crate indépendant gérant la logique pure. Il contient les structures de données (Feed, Article), la persistence (store.rs) et le fetcher asynchrone (fetcher.rs).rss-gui (Binaire / Frontend) : Crate qui importe rss-core. Il utilise eframe et egui pour dessiner l'interface. Il gère l'état de la vue (GuiState) et appelle les fonctions de rss-core.Cargo.workspace) : Le projet est défini comme un "workspace" Cargo, permettant aux deux crates de partager un dossier target (compilation) et un Cargo.lock (dépendances).rss-gui) détient une instance mutable de la structure principale de rss-core et l'appelle directement, mettant à jour son propre état local en réponse.
+ Pour éviter de figer l'interface utilisateur (GUI) lors des requêtes réseau, rss-core utilise tokio, le principal runtime asynchrone de Rust. Le fetcher (récupérateur de flux) est conçu pour s'exécuter dans un thread séparé et communiquer avec la GUI de manière non-bloquante.
+
tokio : Le crate tokio est utilisé pour créer un runtime multi-threadé (tokio::runtime::Runtime) qui gère l'exécution des tâches asynchrones (les async fn).ureq : Le client HTTP ureq est utilisé pour effectuer les requêtes GET. Il est exécuté dans un thread bloquant (tokio::task::spawn_blocking) pour s'intégrer à l'écosystème async.spawn_blocking : C'est la fonction clé qui permet au code synchrone (comme ureq::get()) de s'exécuter sans bloquer le runtime tokio principal, assurant que l'UI reste réactive.Result, permettant à la GUI d'afficher un message d'erreur propre.
+ L'interface est entièrement construite avec egui, un framework de GUI en Rust qui utilise une approche en mode immédiat (immediate mode). Cela signifie que l'interface est redessinée à chaque frame, ce qui simplifie la gestion de l'état et permet un développement très rapide sans callbacks complexes.
+
eframe : C'est le crate qui lance la fenêtre de bureau et exécute la boucle d'application egui.eframe::App : La structure principale de rss-gui implémente ce trait, qui ne requiert qu'une seule méthode : update(). Cette méthode est appelée à chaque frame pour dessiner l'intégralité de l'interface.egui : L'interface est structurée à l'aide de panneaux (egui::SidePanel, egui::CentralPanel) pour diviser l'écran (flux à gauche, articles au centre).GuiState. Les interactions (clics, etc.) modifient directement cet état, et l'interface se redessine automatiquement à la frame suivante.
+ Pour la persistance des données, le projet évite une base de données complexe et opte pour des fichiers JSON. C'est le crate serde (SERialisation/DEserialisation) qui gère la conversion des structures Rust (comme Feed) en texte JSON et vice-versa.
+
serde : Utilisation des macros #[derive(Serialize, Deserialize)] sur toutes les structures de données (Feed, Article, Config).feeds.json, config.json).store.rs : Toute la logique de lecture (store::load()) et d'écriture (store::save()) est centralisée dans ce module de rss-core, qui utilise les fonctions de serde_json.Result, permettant de gérer proprement les erreurs I/O (fichier non trouvé, etc.).Visualisation complète de l'architecture avec tooltips détaillés pour chaque composant.
+