diff --git a/.github/workflows/publish.yml b/.github/workflows/publish.yml new file mode 100644 index 0000000..ec7a751 --- /dev/null +++ b/.github/workflows/publish.yml @@ -0,0 +1,32 @@ +name: Publish to PyPI + +on: + release: + types: [published] + +permissions: + contents: read + +jobs: + publish: + name: Publish to PyPI + runs-on: ubuntu-latest + environment: pypi + permissions: + id-token: write + steps: + - uses: actions/checkout@v4 + + - name: Set up Python + uses: actions/setup-python@v5 + with: + python-version: "3.12" + + - name: Install build tools + run: pip install build + + - name: Build package + run: python -m build + + - name: Publish to PyPI + uses: pypa/gh-action-pypi-publish@release/v1 diff --git a/.gitignore b/.gitignore index e116586..a706fcd 100644 --- a/.gitignore +++ b/.gitignore @@ -23,5 +23,7 @@ htmlcov/ # Textual .textual/ - -venv \ No newline at end of file +.env +venv +TODO.md +CONTEXT.md \ No newline at end of file diff --git a/CONTEXT.md b/CONTEXT.md deleted file mode 100644 index 4a2531c..0000000 --- a/CONTEXT.md +++ /dev/null @@ -1,325 +0,0 @@ -# TUI Notes - Implementation Context - -This document contains technical details, architectural decisions, and implementation guidance for continuing development of the TUI Notes project. - -## Project Vision - -A terminal-based notes application inspired by post-it notes, allowing users to quickly capture and organize thoughts directly from the command line with persistent storage. - -## Technology Stack - -### Core Technologies - -- **Language**: Python 3.8+ -- **TUI Framework**: Textual (recommended) or Rich - - **Why Textual**: Modern, reactive, async-based, great documentation, web-dev-friendly component model - - Alternative: Rich (simpler but less powerful for complex layouts) -- **Data Persistence**: JSON file storage -- **Data Location**: `~/.tui-notes/notes.json` (user home directory) - -### Dependencies (Planned) - -``` -textual>=0.40.0 -pydantic>=2.0.0 # For data validation (optional) -``` - -## Architecture Overview - -### Project Structure - -``` -tui-notes/ -├── tui_notes/ -│ ├── __init__.py -│ ├── __main__.py # Entry point -│ ├── app.py # Main Textual app -│ ├── models.py # Note data models -│ ├── storage.py # File persistence layer -│ ├── widgets/ -│ │ ├── __init__.py -│ │ ├── note_card.py # Individual note widget -│ │ └── note_list.py # Container for multiple notes -│ └── config.py # Configuration and paths -├── tests/ -│ ├── __init__.py -│ ├── test_models.py -│ └── test_storage.py -├── README.md -├── CONTEXT.md -├── requirements.txt -├── setup.py -└── LICENSE -``` - -### Data Model - -```python -# models.py -from dataclasses import dataclass -from datetime import datetime -from typing import List - -@dataclass -class Note: - id: str # UUID - title: str # Note title - content: str # Note content - created_at: datetime # Creation timestamp - updated_at: datetime # Last modified timestamp - order: int # Display order - -@dataclass -class NotesData: - notes: List[Note] - version: str = "1.0" # For future migration support -``` - -### Storage Layer - -**File Location**: `~/.tui-notes/notes.json` - -**Operations**: -- `load_notes()` -> NotesData -- `save_notes(notes: NotesData)` -> None -- `create_note(title: str, content: str)` -> Note -- `update_note(note_id: str, updates: dict)` -> Note -- `delete_note(note_id: str)` -> None -- `reorder_notes(note_ids: List[str])` -> None - -**Implementation Details**: -- Use `pathlib.Path.home()` for cross-platform home directory -- Create directory if it doesn't exist -- Handle JSON encoding/decoding with datetime support -- Atomic writes (write to temp file, then rename) -- Backup mechanism before overwriting - -### UI Components - -#### Main App Layout (Textual) - -``` -┌─────────────────────────────────────┐ -│ TUI Notes - Press Ctrl+Q to quit │ ← Header -├─────────────────────────────────────┤ -│ ┌─────────┐ ┌─────────┐ ┌─────────┐│ -│ │ Note 1 │ │ Note 2 │ │ Note 3 ││ -│ │ Title │ │ Title │ │ Title ││ ← Note Cards (scrollable grid) -│ │ │ │ │ │ ││ -│ │ Content │ │ Content │ │ Content ││ -│ │ ... │ │ ... │ │ ... ││ -│ └─────────┘ └─────────┘ └─────────┘│ -├─────────────────────────────────────┤ -│ Ctrl+N: New | Tab: Navigate | ... │ ← Footer (shortcuts) -└─────────────────────────────────────┘ -``` - -#### Widget Hierarchy - -- **NotesApp** (Textual App) - - **Header** (built-in) - - **NoteList** (Container widget) - - **NoteCard** (Custom widget per note) - - Title input - - Content textarea - - Metadata (created/updated) - - **Footer** (built-in) - -### Key Features Implementation - -#### 1. Note Creation -- Keyboard shortcut triggers modal/dialog -- User inputs title -- New note added with empty content -- Focus moves to new note -- Auto-save triggered - -#### 2. Note Editing -- Focus on note card makes it editable -- Textual's `Input` and `TextArea` widgets -- Reactive updates trigger auto-save (with debouncing) - -#### 3. Note Deletion -- Keyboard shortcut or button -- Confirmation dialog (optional) -- Remove from storage -- Update UI - -#### 4. Note Reordering -- Drag-and-drop (if Textual supports) OR -- Arrow keys + modifier to move position -- Update order property -- Re-render list - -#### 5. Persistence -- Auto-save on every change (debounced 1-2 seconds) -- Manual save on quit -- Load on startup - -### Configuration - -```python -# config.py -from pathlib import Path - -# Paths -APP_DIR = Path.home() / ".tui-notes" -NOTES_FILE = APP_DIR / "notes.json" -BACKUP_DIR = APP_DIR / "backups" - -# Settings -AUTO_SAVE_DELAY = 2 # seconds -MAX_BACKUPS = 5 -DEFAULT_NOTE_TITLE = "Untitled Note" -``` - -## Implementation Phases - -### Phase 1: Foundation -- [x] Set up project structure -- [x] Implement data models -- [x] Create storage layer with JSON persistence -- [x] Write basic tests for storage - -### Phase 2: Basic UI -- [x] Create main Textual app skeleton -- [x] Implement single note card widget -- [x] Add note list container -- [x] Test loading/saving notes - -### Phase 3: Core Features -- [x] Add note creation -- [x] Implement note editing -- [x] Add note deletion -- [x] Implement keyboard shortcuts - -### Phase 4: Advanced Features -- [x] Note reordering -- [ ] Clear note content -- [ ] Search/filter notes -- [ ] Note categories/tags (future) - -### Phase 5: Polish -- [x] Error handling -- [x] User feedback (toasts/notifications) -- [x] Themes/colors -- [ ] Performance optimization -- [x] Comprehensive testing - -## Technical Considerations - -### Async/Await -Textual is async-based. Key points: -- App methods are async -- Event handlers are async -- Use `await` for I/O operations - -### State Management -- App-level state for notes list -- Reactive properties for UI updates -- Textual's reactive system handles re-rendering - -### Error Handling -- File permission errors -- Corrupted JSON data -- Disk full scenarios -- Invalid user input - -### Testing Strategy -- Unit tests for models and storage -- Integration tests for storage + models -- Snapshot tests for UI components (Textual supports this) -- Manual testing for keyboard interactions - -## Development Commands - -```bash -# Development setup -python -m venv venv -source venv/bin/activate # or `venv\Scripts\activate` on Windows -pip install -r requirements.txt - -# Run app -python -m tui_notes - -# Run tests -pytest - -# Format code -black tui_notes/ -isort tui_notes/ - -# Type checking -mypy tui_notes/ -``` - -## Resources - -- **Textual Documentation**: https://textual.textualize.io/ -- **Textual Tutorial**: https://textual.textualize.io/tutorial/ -- **Textual Examples**: https://github.com/Textualize/textual/tree/main/examples -- **Rich Documentation**: https://rich.readthedocs.io/ - -## Next Steps for Implementation - -1. Start with Textual tutorial to understand the framework -2. Create basic project structure -3. Implement data models with tests -4. Build storage layer with file I/O -5. Create simplest possible UI (one note card) -6. Iterate and add features incrementally - -## Design Decisions Log - -- **Why JSON over SQLite?**: Simpler for small dataset, human-readable, easy backup -- **Why Textual over Curses?**: Modern, better DX, reactive model, active development -- **Why local files over cloud?**: Privacy, offline-first, simplicity, no dependencies -- **Data location**: User home directory follows Unix convention for user data -- **Swap by data, not by widget**: Textual não suporta `move_before` — swap de post-its troca title/content entre widgets - -## Current Implementation Status - -### Concluído (PLAN 01-09 + Refactoring) -- ✅ Estrutura do projeto com pyproject.toml, entry point `tui-notes` -- ✅ Grid 3x3 com widget PostIt (Container, propriedades reativas) -- ✅ 6 cores alternadas (amarelo, verde, azul, rosa, laranja, roxo) -- ✅ EmptySlot placeholder em posições vazias -- ✅ Modal de edição (EditPostItScreen) com Input + TextArea -- ✅ Adicionar (`a`) e remover (`d`, com confirmação) post-its -- ✅ Grid sempre mantém 9 filhos (PostIt + EmptySlot) -- ✅ Modo Move (`m` + setas) com swap entre PostIt↔PostIt e PostIt↔EmptySlot -- ✅ Navegação por setas no modo normal -- ✅ Feedback visual: foco (borda branca), moving (borda laranja) -- ✅ Persistência JSON em ~/.config/tui-notes/ (atomic writes) -- ✅ Auto-save em add/delete/edit/move + Ctrl+S/Ctrl+R -- ✅ Cores personalizadas (`c` — 6 cores com modal) -- ✅ Exportação Markdown (`Ctrl+E`) -- ✅ Help Screen (`?`) -- ✅ 30 testes (pytest), pylint 10/10, black + isort -- ✅ README.md completo, pip install funcional -- ✅ Refactoring SOLID/DRY/KISS (widgets/, screens/, constants.py) -- ✅ Type hints e docstrings em todos os métodos - -### Pendente -- ⚠️ Atalhos numéricos (1-9) para posição direta (PLAN 05) -- ⚠️ Busca e filtros (PLAN 07.2) -- ⚠️ Temas claro/escuro (PLAN 07.3) -- 📋 CHANGELOG.md (PLAN 09) -- 📋 PyPI publishing (PLAN 09, opcional) -- 📋 GitHub Release + CI/CD (PLAN 09, opcional) -- 📋 Testes em macOS/Windows (PLAN 09) - -### Não Implementado (decisão consciente) -- ~~Drag & Drop~~ — Textual não suporta nativamente - -## Future Enhancements - -- Export notes to markdown -- Import from other formats -- Sync between devices (optional) -- Note templates -- Rich text formatting (limited by terminal) -- Tags and categories -- Search functionality -- Dark/light themes -- Note sharing/export diff --git a/TODO.md b/TODO.md deleted file mode 100644 index 756c506..0000000 --- a/TODO.md +++ /dev/null @@ -1,22 +0,0 @@ -# TUI Notes — TODO - -## Itens Pendentes por Plano - -- [ ] Criar CHANGELOG.md - -- [ ] Criar conta no PyPI -- [ ] Configurar token de autenticação -- [ ] Build: `python -m build` -- [ ] Upload: `twine upload dist/*` -- [ ] Testar instalação: `pip install tui-notes` - -- [ ] Criar tag de versão (v1.0.0) -- [ ] Criar release no GitHub -- [ ] Adicionar notas de lançamento - -- [ ] GitHub Actions para publicação automática no PyPI - -- [ ] Testar em macOS (se disponível) -- [ ] Testar em Windows (se disponível) - ---- diff --git a/pyproject.toml b/pyproject.toml index d0fe652..2ad9b7f 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -41,8 +41,8 @@ dev = [ tui-notes = "tui_notes.__main__:main" [project.urls] -Homepage = "https://github.com/douglas/tui-notes" -Repository = "https://github.com/douglas/tui-notes" +Homepage = "https://github.com/Douglas019BR/tui-notes" +Repository = "https://github.com/Douglas019BR/tui-notes" [tool.hatch.build.targets.wheel] packages = ["tui_notes"]