# Contexto do Projeto Atua como um programador Rust sénior e especialista em interfaces de terminal (TUI). O teu objetivo é implementar uma aplicação de gestão de tarefas de linha de comandos (CLI/TUI) que se integra com o Google Tasks. A aplicação deve adotar a filosofia "Offline-First", guardando as tarefas localmente e sincronizando com a cloud em pano de fundo quando houver ligação à internet. # Stack Tecnológica * **Linguagem:** Rust * **UI:** `ratatui` + `crossterm` * **Assincronismo:** `tokio` * **HTTP:** `reqwest` * **Autenticação:** `yup-oauth2` (usando o Device Authorization Flow) * **Base de Dados Local:** `rusqlite` (SQLite local para guardar tarefas e fila de sincronização) * **Serialização:** `serde` + `serde_json` # Arquitetura de Ficheiros (Clean Architecture + MVU) Organiza o código estritamente com a seguinte estrutura: ```text src/ ├── main.rs # Ponto de entrada, inicialização do terminal e DB ├── app.rs # Estado da aplicação (App struct) e processamento de eventos ├── domain/ # Lógica pura e modelos de dados │ ├── mod.rs │ └── models.rs # Structs de Tarefa, Lista e Eventos de Sincronização ├── ui/ # Renderização Ratatui │ ├── mod.rs # Layout principal │ └── components.rs # Widgets (Tabs, Listas, Pop-ups) └── infrastructure/ # Efeitos colaterais e I/O ├── mod.rs ├── db.rs # Inicialização do SQLite, queries CRUD e fila offline └── api.rs # Integração com Google Tasks API e OAuth2 ``` # Requisitos Principais ## 1. Interface de Utilizador (UI) e Layout * O ecrã deve estar dividido numa grelha rigorosa: * **Topo (Tabs):** Uma linha horizontal a representar as **Listas de Tarefas**. Deve ser possível navegar entre elas e adicionar novas listas. * **Corpo Principal (Split View):** Abaixo das listas, o ecrã divide-se em dois painéis verticais: * **Painel da Esquerda (Lista de Tasks):** Apresenta as tarefas da lista atualmente selecionada. A data e hora dos lembretes (`due dates`) devem ser visíveis diretamente nesta lista, ao lado ou por baixo do título da tarefa. * **Painel da Direita (Detalhes):** Mostra as notas, descrição longa e/ou sub-tarefas da tarefa atualmente selecionada no painel esquerdo. ## 2. Interação e Atalhos (UX) * **Navegação de Painéis:** A mudança de foco entre os três grandes blocos (Tabs no Topo, Painel Esquerdo e Painel Direito) deve ser feita usando a combinação de teclas `Tab + Setas`. * **Navegação Interna:** Uma vez dentro de um painel, a navegação entre os itens faz-se apenas com as setas do teclado (não usar atalhos tipo Vim com `j/k`). * **Reordenação Persistente:** O utilizador deve conseguir organizar as tarefas na lista usando o atalho `Alt + Setas` (Cima/Baixo). Esta ordenação customizada tem de ficar gravada na base de dados para se manter exatamente igual entre sessões. * **Operações CRUD:** Deve ser possível Adicionar, Editar e Apagar qualquer Lista ou Tarefa. * **Edição de Datas (Pop-up):** Quando o utilizador for editar a data/hora de uma tarefa, a aplicação deve abrir um modal/Pop-up interativo sobreposto ao centro do ecrã para facilitar a introdução desses dados. * O estado da rede ("Online" / "Offline" / "A Sincronizar...") deve ser apresentado num rodapé discreto. ## 3. Base de Dados Local (Offline-First) * Usa o SQLite para criar um ficheiro local (ex: `tasks.db`). * **Tabela `tasks`:** Deve espelhar a estrutura de uma Google Task (ID, Title, Notes, Status, Due, Position/Order). A coluna de posição é crítica para garantir que a ordenação do utilizador não se perde ao reiniciar a aplicação. * **Tabela `sync_queue`:** Fundamental para o funcionamento offline. Deve registar a ação pendente (CREATE, UPDATE, DELETE, REORDER), o ID local/remoto e o payload em JSON. * A interface (`app.rs` e `ui/`) lê **exclusivamente** do SQLite, garantindo que o carregamento da interface é imediato e não bloqueia à espera de respostas de rede. ## 4. Motor de Sincronização (Sync Engine) * Quando o utilizador cria, edita, apaga ou reordena uma tarefa, a ação e a nova ordem (position) são registadas no SQLite. * Uma *task* assíncrona do Tokio processa a fila de sincronização em pano de fundo quando deteta ligação à internet, chamando a API oficial do Google Tasks via `reqwest`. A reordenação deve refletir-se também na cloud. * Se não houver token de acesso guardado, a TUI deve apresentar um Pop-up a pedir para o utilizador visitar o URL de autorização e introduzir o código gerado pelo `yup-oauth2`.