From b04dc992d9008e88725514e992cfb83887ddf5f6 Mon Sep 17 00:00:00 2001 From: Michael SCHAL Date: Fri, 13 Feb 2026 08:41:56 +0100 Subject: [PATCH] fix(focus): prevent card rebound on swipe release by freezing exit position --- README.md | 177 ++++++++++++-------- web/src/components/focus/FocusCardStack.tsx | 6 +- 2 files changed, 113 insertions(+), 70 deletions(-) diff --git a/README.md b/README.md index f9c6817..699499d 100644 --- a/README.md +++ b/README.md @@ -1,81 +1,124 @@ -# FlowReader +# 🌿 FlowReader -A minimalist, self-hosted RSS/Atom reader focused on simplicity and resource efficiency. +> **Le calme dans le chaos de l'information.** +> Un agrégateur RSS minimaliste, intelligent et économe, conçu pour ceux qui veulent reprendre le contrôle de leur veille. -## Quick Start +![FlowReader Dashboard](docs/dashboard.png) + +[![Go Version](https://img.shields.io/badge/Go-1.24-00ADD8?style=flat-square&logo=go)](https://golang.org/) +[![React Version](https://img.shields.io/badge/React-19-61DAFB?style=flat-square&logo=react)](https://react.dev/) +[![Docker](https://img.shields.io/badge/Docker-Ready-2496ED?style=flat-square&logo=docker)](https://www.docker.com/) +[![License](https://img.shields.io/badge/License-MIT-yellow.svg?style=flat-square)](LICENSE) + +## ✨ Pourquoi FlowReader ? + +FlowReader n'est pas juste un autre lecteur RSS. C'est une expérience de lecture repensée pour l'efficacité et le plaisir. Fini le scroll infini anxiogène, place à la concentration. + +### 🧘 Mode Focus + +Une interface immersive inspirée des applications de rencontre pour trier vos flux à la vitesse de la pensée. + +- **Swipe à droite :** Article lu / archivé. +- **Swipe à gauche :** Article gardé pour plus tard. +- **Double-clic :** Lecture immédiate. + +![Mode Focus](docs/focus.png) + +### 🧠 Smart Digest (IA) + +Ne perdez plus de temps sur les articles "clickbait". + +- FlowReader utilise l'IA (via OpenRouter) pour lire le contenu complet à votre place. +- Il génère un **résumé concis** directement accessible depuis votre liste de lecture. +- Identifiez en un coup d'œil si un article mérite votre temps. + +![Smart Digest](docs/digest.png) + +### ⚡ Performance & Sobriété + +Conçu pour l'auto-hébergement respectueux des ressources. + +- **Backend en Go :** Ultra-rapide et compilé. +- **Frontend React 19 :** Fluide et moderne. +- **< 150MB RAM :** Tourne parfaitement sur un Raspberry Pi ou un NAS modeste. + +## 🚀 Fonctionnalités Clés + +- **PWA & Offline :** Installez-le sur mobile comme une app native. Supporte la lecture hors-ligne. +- **Recherche Full-Text :** Retrouvez n'importe quel article instantanément grâce à l'indexation PostgreSQL. +- **Design Organique :** Thèmes "Organic Warmth" et "Deep Forest" (Mode Sombre) pour le confort des yeux. +- **Lecture Confortable :** Mode lecteur distration-free intégré. +- **Agents IA (BMad) :** Architecture conçue pour être maintenue et étendue par des agents IA. + +## 📦 Installation + +### Option 1 : Docker Compose (Recommandé) + +Le moyen le plus simple de démarrer. ```bash -# Start with Docker Compose -docker-compose up --build +# 1. Cloner le dépôt +git clone https://github.com/R0m1k3/FlowReader.git +cd FlowReader -# Or use Make +# 2. Lancer la stack +docker-compose up -d +``` + +Accédez à `http://localhost:8080`. + +### Option 2 : Unraid + +Un template dédié est fourni pour les utilisateurs d'Unraid. + +1. Copiez le fichier `docker-compose.unraid.yaml` sur votre serveur. +2. Lancez le conteneur : + + ```bash + docker-compose -f docker-compose.unraid.yaml up -d + ``` + + *Note : Les données sont persistées dans `/mnt/user/appdata/flowreader`.* + +### Configuration (Variables d'Environnement) + +| Variable | Description | Défaut | +|----------|-------------|--------| +| `PORT` | Port du serveur | `8080` | +| `DATABASE_URL` | Connexion PostgreSQL | `postgres://...` | +| `OPENROUTER_API_KEY` | Clé pour les résumés IA | *(Optionnel)* | + +## 🛠️ Développement + +Envie de mettre les mains dans le code ? + +```bash +# Pré-requis : Go 1.22+, Node 20+, Docker + +# 1. Lancer les services (DB) make docker-up + +# 2. Lancer le backend (avec reload) +make dev-backend + +# 3. Lancer le frontend +make dev-frontend ``` -Access the API: `http://localhost:8080` +## 🏗️ Architecture -## Deployment - -### Unraid - -A dedicated configuration file `docker-compose.unraid.yaml` is provided for Unraid servers. It pulls the pre-built image from GitHub Container Registry. - -1. Copy **only** `docker-compose.unraid.yaml` to your Unraid server (e.g. into `/mnt/user/appdata/flowreader`). -2. Run with Docker Compose: - -```bash -docker-compose -f docker-compose.unraid.yaml up -d +```mermaid +graph TD + Client[React Frontend] -->|API REST| Server[Go Backend] + Server -->|SQL| DB[(PostgreSQL)] + Server -->|Fetch| RSS[Flux RSS Externes] + Server -->|Analyze| AI[OpenRouter API] ``` -Note: The configuration uses `/mnt/user/appdata/flowreader/postgres_data` for database persistence. +## 🤝 Contribuer +Les contributions sont les bienvenues ! N'hésitez pas à ouvrir une Issue ou une Pull Request. -## Development +## 📄 Licence -```bash -# Run locally (requires Go 1.22+) -make dev - -# Run tests -make test - -# Lint code -make lint -``` - -## Project Structure - -``` -flowreader/ -├── cmd/ -│ └── server/ # Application entry point -├── internal/ -│ ├── domain/ # Business logic (entities, services) -│ ├── handler/ # HTTP handlers -│ └── repository/ # Database access -├── pkg/ # Shared utilities -└── migrations/ # SQL migrations -``` - -## Tech Stack - -- **Backend**: Go 1.24+ (Chi, pgx, gofeed) -- **Database**: PostgreSQL 16 -- **Frontend**: React 19 + Vite + Tailwind 4 ("Organic Warmth" Theme) -- **Auth**: Session-based (HTTP-only cookies) -- **Feeds**: RSS/Atom with Favicon extraction - -## Current Status (MVP) - -- [x] User Management (Register/Login) -- [x] Feed Management (Add/Import/Refresh) -- [x] Reader Experience (Grid/List View, infinite scroll) -- [x] Theme: Organic Warmth (Carbon/Gold/Paper) - -## Memory Target - -Total container footprint: **< 150MB RAM** - -## License - -MIT +Ce projet est sous licence MIT. Voir le fichier [LICENSE](LICENSE) pour plus de détails. diff --git a/web/src/components/focus/FocusCardStack.tsx b/web/src/components/focus/FocusCardStack.tsx index 7a1bb22..2600576 100644 --- a/web/src/components/focus/FocusCardStack.tsx +++ b/web/src/components/focus/FocusCardStack.tsx @@ -24,7 +24,7 @@ interface FocusCardStackProps { export function FocusCardStack({ articles, onMarkRead, onKeep, onToggleFavorite, onEmpty }: FocusCardStackProps) { const [currentIndex, setCurrentIndex] = useState(0); const [readingArticle, setReadingArticle] = useState
(null); - // const [exitX, setExitX] = useState(0); // Removed per simplification + const [exitX, setExitX] = useState(0); const isMobile = useIsMobile(); const [isProcessing, setIsProcessing] = useState(false); @@ -84,7 +84,7 @@ export function FocusCardStack({ articles, onMarkRead, onKeep, onToggleFavorite, if (!active && trigger) { // Swipe Validé const isRight = mx > 0; - // setExitX(isRight ? 500 : -500); // Trigger exit animation - Removed lateral movement per user request + setExitX(x.get()); // Capture current position to freeze exit animation // Trigger action via handler handleAction(isRight ? 'read' : 'keep'); @@ -208,7 +208,7 @@ export function FocusCardStack({ articles, onMarkRead, onKeep, onToggleFavorite, } }} animate={{ scale: 1 - i * 0.05, y: i * 20 }} - exit={{ opacity: 0, scale: 0.9, transition: { duration: 0.2 } }} + exit={{ x: exitX, opacity: 0, scale: 0.9, transition: { duration: 0.2 } }} >