10 Commits
Author SHA1 Message Date
Lucas Rayan Guerra 9c5df497a5 Merge pull request #51 from lucasrguerra/release/1.3.1
Release / Cria a release (push) Canceled after 0s
Release / CLI (linux-aarch64) (push) Canceled after 0s
Release / CLI (linux-x86_64) (push) Canceled after 0s
Release / CLI (macos-aarch64) (push) Canceled after 0s
Release / CLI (macos-x86_64) (push) Canceled after 0s
Release / CLI (windows-x86_64) (push) Canceled after 0s
Release / App desktop (linux-x86_64) (push) Canceled after 0s
Release / App desktop (macos-aarch64) (push) Canceled after 0s
Release / App desktop (macos-x86_64) (push) Canceled after 0s
Release / App desktop (windows-x86_64) (push) Canceled after 0s
Release / Publica a release (push) Canceled after 0s
release: 1.3.1
2026-10-23 12:20:02 -03:00
Lucas RayanandClaude Sonnet 5.5 3946adda09 release: 1.3.1
Só a logo nova: o guará com o anel laranja, uma arte transparente para os dois temas, no app, no
favicon, nos ícones e no README. Sem mudança de comportamento.

Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
2026-10-23 12:16:11 -03:00
Lucas Rayan Guerra f0a5f43c77 Merge pull request #50 from lucasrguerra/feat/nova-logo
Logo oficial: o guará com o anel laranja (arte final do autor)
2026-10-23 12:09:54 -03:00
Lucas RayanandClaude Sonnet 5.5 05340bd8d2 Logo oficial: a versão final do autor (guara.png), sem recorte nosso
O autor gerou a logo já sem fundo; ela passa a ser a arte oficial, usada em qualquer tema, e não é
mais alterada. scripts/processar-logo.py (que tirava o fundo) e a arte original com fundo saem;
scripts/gerar-logo.py só deriva guara-s.png (barra lateral e favicon) e o ícone do app, e os ícones
do Tauri são regenerados.

Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
2026-10-23 12:05:58 -03:00
Lucas RayanandClaude Sonnet 5.5 0a9622fb96 Logo única: guara.png e guara-s.png
A variante clara tinha artefatos; a arte escura recortada serve aos dois temas. Saem a troca de
variante por tema, os arquivos -light e a fonte clara; os arquivos escuros viram guara.png e
guara-s.png e o script, o app, o servidor do guara ui e o README usam só eles.

Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
2026-10-23 11:58:39 -03:00
Lucas RayanandClaude Sonnet 5.5 9c09f5dd8a Nova logo oficial: o guará com o anel laranja
A arte do usuário (assets/logo/*-fonte.png) passa a ser a logo do projeto. scripts/processar-logo.py
tira o fundo (só o que toca a borda e os bolsões internos, com a faixa da borda refeita pela cor
real do desenho, sem halo) e gera as variantes clara e escura (768 e 128 px) e o ícone do app. O app
escolhe a variante pelo tema (barra lateral, topo e tela inicial), o favicon e o servidor do guara ui
passam a PNG, os ícones do Tauri são regenerados e o README usa <picture> para claro e escuro. A logo
SVG antiga e o gerador dela saem.

Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
2026-10-23 11:56:36 -03:00
Lucas Rayan Guerra 82c1fb6c8f Merge pull request #49 from lucasrguerra/dev/verificacao-local
Verificação local (scripts/verificar.sh), pre-push e CI que pula só documentação
2026-10-23 11:38:19 -03:00
Lucas Rayan Guerra 13bf00030d Merge pull request #48 from lucasrguerra/ci/apt-cache-ownership
CI: devolve a posse do cache do apt ao usuário (o cache não estava sendo gravado)
2026-10-23 11:37:54 -03:00
Lucas RayanandClaude Sonnet 5.5 9d67890b68 Verificação local (scripts/verificar.sh), hook de pre-push e CI que pula só documentação
scripts/verificar.sh roda em segundos o mesmo que o CI roda (fmt, clippy -D warnings no workspace
inteiro, tradução, scripts, workflows) e, com --completo, os testes e o cargo audit. O hook de
pre-push (scripts/instalar-hooks.sh) a roda antes de cada push. O CI deixa de rodar em mudanças
só de documentação.

Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
2026-10-23 11:22:23 -03:00
Lucas RayanandClaude Sonnet 5.5 f8fa5f79d5 CI: devolve a posse do cache do apt ao usuário (o cache não estava sendo gravado)
O apt roda como root e deixa arquivos ilegíveis para o usuário do runner; o actions/cache
falhava com 'tar failed with exit code 2' e nunca salvava, então o cache dos .deb não valia.

Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
2026-10-23 11:18:54 -03:00
78 changed files with 171 additions and 85 deletions

No files matched your search

+3
View File
@@ -0,0 +1,3 @@
#!/usr/bin/env bash
# Antes de cada push: a verificação rápida. Ignore com `git push --no-verify` (use com parcimônia).
exec "$(git rev-parse --show-toplevel)/scripts/verificar.sh"
+3
View File
@@ -1,9 +1,12 @@
name: CI name: CI
on: on:
# Mudança só de documentação não precisa de 6 jobs em 3 sistemas.
push: push:
branches: [main] branches: [main]
paths-ignore: ['**.md', 'docs/**', 'LICENSE*', '.gitignore', '.githooks/**']
pull_request: pull_request:
paths-ignore: ['**.md', 'docs/**', 'LICENSE*', '.gitignore', '.githooks/**']
concurrency: concurrency:
group: ci-${{ github.ref }} group: ci-${{ github.ref }}
+11
View File
@@ -4,6 +4,17 @@
Format based on [Keep a Changelog](https://keepachangelog.com/en/1.1.0/); versions follow SemVer. Format based on [Keep a Changelog](https://keepachangelog.com/en/1.1.0/); versions follow SemVer.
## [1.3.1] - 2026-10-23
### Changed
- **New official logo:** the maned wolf (guará) inside the orange ring, drawn by the project's author, with a transparent background so the same art works in the light and dark themes. It replaces the old track-disc logo in the app (sidebar, top bar and home screen), the favicon, the desktop app icons and the README.
- `guara ui` serves the new `guara.png` and `guara-s.png`; `scripts/gerar-logo.py` derives the small logo and the app icon from the official art.
- Development: `scripts/verificar.sh` runs locally what the CI runs, with an optional pre-push hook (`scripts/instalar-hooks.sh`), and the CI no longer runs on documentation-only changes.
### Notes
- No change to scanning, recovery, signing or any other behavior. This is the first release after the in-app updater: an app on 1.3.0 should offer **Update now**.
- The screenshots in `docs/img/` still show the old logo and will be redone.
## [1.3.0] - 2026-10-23 ## [1.3.0] - 2026-10-23
### Added ### Added
+11
View File
@@ -4,6 +4,17 @@
Formato baseado em [Keep a Changelog](https://keepachangelog.com/pt-BR/1.1.0/); versões seguem SemVer. Formato baseado em [Keep a Changelog](https://keepachangelog.com/pt-BR/1.1.0/); versões seguem SemVer.
## [1.3.1] - 2026-10-23
### Alterado
- **Logo oficial nova:** o guará dentro do anel laranja, desenhado pelo autor do projeto, com fundo transparente para a mesma arte servir aos temas claro e escuro. Ela substitui a logo antiga das trilhas de disco no app (barra lateral, topo e tela inicial), no favicon, nos ícones do app desktop e no README.
- O `guara ui` serve os novos `guara.png` e `guara-s.png`; o `scripts/gerar-logo.py` deriva a logo pequena e o ícone do app da arte oficial.
- Desenvolvimento: o `scripts/verificar.sh` roda localmente o que o CI roda, com um hook opcional de pre-push (`scripts/instalar-hooks.sh`), e o CI deixa de rodar em mudanças só de documentação.
### Notas
- Nenhuma mudança na varredura, na recuperação, na assinatura ou em qualquer outro comportamento. É a primeira versão depois do atualizador do app: um app na 1.3.0 deve oferecer **Atualizar agora**.
- Os screenshots em `docs/img/` ainda mostram a logo antiga e serão refeitos.
## [1.3.0] - 2026-10-23 ## [1.3.0] - 2026-10-23
### Adicionado ### Adicionado
+5 -3
View File
@@ -11,11 +11,13 @@ Thanks for helping! Golden rules:
## Workflow ## Workflow
```bash ```bash
cargo fmt --all scripts/instalar-hooks.sh # uma vez: roda a verificação rápida antes de cada push
cargo clippy --workspace --all-targets scripts/verificar.sh # rápido (segundos): fmt, clippy como no CI, tradução, scripts, workflows
cargo test --workspace scripts/verificar.sh --completo # inclui cargo test --workspace e cargo audit
``` ```
The CI takes 5 to 30 minutes on three systems, so run the check before pushing: almost everything that makes the CI fail shows up locally in seconds. Documentation-only changes (`*.md`, `docs/`) skip the CI.
On Linux the tests build images with `mtools`, `ntfs-3g`, `e2fsprogs`, `exfatprogs`, `imagemagick`, `zip` and `python3`. Without these tools the image tests are skipped (set `GUARA_REQUIRE_FIXTURES=1` to make them fail). On Linux the tests build images with `mtools`, `ntfs-3g`, `e2fsprogs`, `exfatprogs`, `imagemagick`, `zip` and `python3`. Without these tools the image tests are skipped (set `GUARA_REQUIRE_FIXTURES=1` to make them fail).
For the external reference images (BitLocker, FileVault 2, dfvfs, AFF4), run `scripts/fetch-testdata.sh`; without them those tests are skipped. The BitLocker test takes about 75 s. For the external reference images (BitLocker, FileVault 2, dfvfs, AFF4), run `scripts/fetch-testdata.sh`; without them those tests are skipped. The BitLocker test takes about 75 s.
+5 -3
View File
@@ -11,11 +11,13 @@ Obrigado por ajudar! Regras de ouro:
## Fluxo ## Fluxo
```bash ```bash
cargo fmt --all scripts/instalar-hooks.sh # uma vez: roda a verificação rápida antes de cada push
cargo clippy --workspace --all-targets scripts/verificar.sh # rápido (segundos): fmt, clippy como no CI, tradução, scripts, workflows
cargo test --workspace scripts/verificar.sh --completo # inclui cargo test --workspace e cargo audit
``` ```
O CI leva de 5 a 30 minutos em três sistemas, então rode a verificação antes do push: quase tudo que faz o CI falhar aparece aqui em segundos. Mudanças só de documentação (`*.md`, `docs/`) pulam o CI.
No Linux os testes geram imagens com `mtools`, `ntfs-3g`, `e2fsprogs`, `exfatprogs`, `imagemagick`, `zip` e `python3`. Sem essas ferramentas os testes com imagem são ignorados (defina `GUARA_REQUIRE_FIXTURES=1` para falhar). No Linux os testes geram imagens com `mtools`, `ntfs-3g`, `e2fsprogs`, `exfatprogs`, `imagemagick`, `zip` e `python3`. Sem essas ferramentas os testes com imagem são ignorados (defina `GUARA_REQUIRE_FIXTURES=1` para falhar).
Para as imagens de referência externas (BitLocker, FileVault 2, dfvfs, AFF4), rode `scripts/fetch-testdata.sh`; sem elas esses testes são pulados. O teste de BitLocker leva cerca de 75 s. Para as imagens de referência externas (BitLocker, FileVault 2, dfvfs, AFF4), rode `scripts/fetch-testdata.sh`; sem elas esses testes são pulados. O teste de BitLocker leva cerca de 75 s.
Generated
+2 -2
View File
@@ -416,7 +416,7 @@ dependencies = [
[[package]] [[package]]
name = "guara-cli" name = "guara-cli"
version = "1.3.0" version = "1.3.1"
dependencies = [ dependencies = [
"clap", "clap",
"ctrlc", "ctrlc",
@@ -429,7 +429,7 @@ dependencies = [
[[package]] [[package]]
name = "guara-core" name = "guara-core"
version = "1.3.0" version = "1.3.1"
dependencies = [ dependencies = [
"aes", "aes",
"argon2", "argon2",
+1 -1
View File
@@ -3,7 +3,7 @@ resolver = "2"
members = ["crates/guara-core", "crates/guara-cli"] members = ["crates/guara-core", "crates/guara-cli"]
[workspace.package] [workspace.package]
version = "1.3.0" version = "1.3.1"
edition = "2021" edition = "2021"
license = "MIT OR Apache-2.0" license = "MIT OR Apache-2.0"
repository = "https://github.com/lucasrguerra/guara" repository = "https://github.com/lucasrguerra/guara"
+1 -1
View File
@@ -1,4 +1,4 @@
<p align="center"><img src="apps/gui/ui/guara-logo.svg" width="360" alt="Guará"></p> <p align="center"><img src="apps/gui/ui/guara.png" width="300" alt="Guará"></p>
<h1 align="center">Guará</h1> <h1 align="center">Guará</h1>
<p align="center">Free file recovery for hard drives, SSDs and USB sticks.<br>Terminal and graphical interface · Windows, Linux and macOS · read-only on the source.</p> <p align="center">Free file recovery for hard drives, SSDs and USB sticks.<br>Terminal and graphical interface · Windows, Linux and macOS · read-only on the source.</p>
+1 -1
View File
@@ -1,4 +1,4 @@
<p align="center"><img src="apps/gui/ui/guara-logo.svg" width="360" alt="Guará"></p> <p align="center"><img src="apps/gui/ui/guara.png" width="300" alt="Guará"></p>
<h1 align="center">Guará</h1> <h1 align="center">Guará</h1>
<p align="center">Recuperação de arquivos livre e gratuita para HD, SSD e pendrive.<br>Terminal e interface gráfica · Windows, Linux e macOS · somente leitura na origem.</p> <p align="center">Recuperação de arquivos livre e gratuita para HD, SSD e pendrive.<br>Terminal e interface gráfica · Windows, Linux e macOS · somente leitura na origem.</p>
+2 -1
View File
@@ -28,10 +28,11 @@ Legend: ✅ done · 🟡 partial · 🔜 planned · 🔭 long-term idea · ⛔ o
| 1.1.0 | 2026-10-20 | Core messages and dates in English, automated translation check, RustCrypto on digest 0.11, verified Docker device access and Superset workspaces | | 1.1.0 | 2026-10-20 | Core messages and dates in English, automated translation check, RustCrypto on digest 0.11, verified Docker device access and Superset workspaces |
| 1.2.0 | 2026-10-22 | QCOW2, VMDK, VHD, VHDX and DMG virtual disks, hash-chained audit trail, PDF report, APFS free-space map | | 1.2.0 | 2026-10-22 | QCOW2, VMDK, VHD, VHDX and DMG virtual disks, hash-chained audit trail, PDF report, APFS free-space map |
| 1.3.0 | 2026-10-23 | Update from inside the app, Ed25519 signatures, differencing QCOW2/VMDK and LZFSE DMG, reference images tested on Linux, macOS and Windows, XFS real-deletion test | | 1.3.0 | 2026-10-23 | Update from inside the app, Ed25519 signatures, differencing QCOW2/VMDK and LZFSE DMG, reference images tested on Linux, macOS and Windows, XFS real-deletion test |
| 1.3.1 | 2026-10-23 | New official logo |
Details of each version in the [CHANGELOG](CHANGELOG.md). Details of each version in the [CHANGELOG](CHANGELOG.md).
## Current status (1.3.0) against what is expected from a forensic suite ## Current status (1.3.1) against what is expected from a forensic suite
### 1. File systems with metadata ### 1. File systems with metadata
+2 -1
View File
@@ -28,10 +28,11 @@ Legenda: ✅ feito · 🟡 parcial · 🔜 planejado · 🔭 ideia a longo prazo
| 1.1.0 | 2026-10-20 | Mensagens do núcleo e datas em inglês, verificação automática da tradução, RustCrypto em digest 0.11, acesso a dispositivo no Docker e workspaces do Superset verificados | | 1.1.0 | 2026-10-20 | Mensagens do núcleo e datas em inglês, verificação automática da tradução, RustCrypto em digest 0.11, acesso a dispositivo no Docker e workspaces do Superset verificados |
| 1.2.0 | 2026-10-22 | Discos virtuais QCOW2, VMDK, VHD, VHDX e DMG, trilha de auditoria encadeada por hash, relatório em PDF, mapa de espaço livre do APFS | | 1.2.0 | 2026-10-22 | Discos virtuais QCOW2, VMDK, VHD, VHDX e DMG, trilha de auditoria encadeada por hash, relatório em PDF, mapa de espaço livre do APFS |
| 1.3.0 | 2026-10-23 | Atualização pelo próprio app, assinaturas Ed25519, QCOW2/VMDK diferenciais e DMG com LZFSE, imagens de referência testadas em Linux, macOS e Windows, teste de exclusão real do XFS | | 1.3.0 | 2026-10-23 | Atualização pelo próprio app, assinaturas Ed25519, QCOW2/VMDK diferenciais e DMG com LZFSE, imagens de referência testadas em Linux, macOS e Windows, teste de exclusão real do XFS |
| 1.3.1 | 2026-10-23 | Nova logo oficial |
Detalhes de cada versão no [CHANGELOG](CHANGELOG.pt-BR.md). Detalhes de cada versão no [CHANGELOG](CHANGELOG.pt-BR.md).
## Situação atual (1.3.0) contra o que se espera de uma suíte forense ## Situação atual (1.3.1) contra o que se espera de uma suíte forense
### 1. Sistemas de arquivos com metadados ### 1. Sistemas de arquivos com metadados
+1 -1
View File
@@ -3,7 +3,7 @@
[package] [package]
name = "guara-gui" name = "guara-gui"
description = "Guará: interface gráfica de recuperação de arquivos" description = "Guará: interface gráfica de recuperação de arquivos"
version = "1.3.0" version = "1.3.1"
edition = "2021" edition = "2021"
license = "MIT OR Apache-2.0" license = "MIT OR Apache-2.0"
repository = "https://github.com/lucasrguerra/guara" repository = "https://github.com/lucasrguerra/guara"
Binary file not shown.

Before

Width:  |  Height:  |  Size: 13 KiB

After

Width:  |  Height:  |  Size: 18 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 29 KiB

After

Width:  |  Height:  |  Size: 51 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 1.8 KiB

After

Width:  |  Height:  |  Size: 2.2 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 4.7 KiB

After

Width:  |  Height:  |  Size: 6.2 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 9.6 KiB

After

Width:  |  Height:  |  Size: 14 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 15 KiB

After

Width:  |  Height:  |  Size: 21 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 15 KiB

After

Width:  |  Height:  |  Size: 23 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 32 KiB

After

Width:  |  Height:  |  Size: 59 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 1.6 KiB

After

Width:  |  Height:  |  Size: 2.1 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 35 KiB

After

Width:  |  Height:  |  Size: 67 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 2.8 KiB

After

Width:  |  Height:  |  Size: 3.6 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 5.6 KiB

After

Width:  |  Height:  |  Size: 7.3 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 7.5 KiB

After

Width:  |  Height:  |  Size: 10 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 3.4 KiB

After

Width:  |  Height:  |  Size: 4.3 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 5.4 KiB

After

Width:  |  Height:  |  Size: 6.1 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 17 KiB

After

Width:  |  Height:  |  Size: 26 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 5.9 KiB

After

Width:  |  Height:  |  Size: 6.4 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 3.0 KiB

After

Width:  |  Height:  |  Size: 3.3 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 9.7 KiB

After

Width:  |  Height:  |  Size: 14 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 3.2 KiB

After

Width:  |  Height:  |  Size: 3.5 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 8.2 KiB

After

Width:  |  Height:  |  Size: 9.5 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 23 KiB

After

Width:  |  Height:  |  Size: 39 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 9.2 KiB

After

Width:  |  Height:  |  Size: 10 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 15 KiB

After

Width:  |  Height:  |  Size: 18 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 37 KiB

After

Width:  |  Height:  |  Size: 72 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 17 KiB

After

Width:  |  Height:  |  Size: 19 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 23 KiB

After

Width:  |  Height:  |  Size: 27 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 52 KiB

After

Width:  |  Height:  |  Size: 111 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 26 KiB

After

Width:  |  Height:  |  Size: 29 KiB

Binary file not shown.
Binary file not shown.

Before

Width:  |  Height:  |  Size: 41 KiB

After

Width:  |  Height:  |  Size: 65 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 64 KiB

After

Width:  |  Height:  |  Size: 145 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 835 B

After

Width:  |  Height:  |  Size: 1.1 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 2.3 KiB

After

Width:  |  Height:  |  Size: 3.0 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 2.3 KiB

After

Width:  |  Height:  |  Size: 3.0 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 4.1 KiB

After

Width:  |  Height:  |  Size: 5.5 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 1.5 KiB

After

Width:  |  Height:  |  Size: 1.9 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 3.8 KiB

After

Width:  |  Height:  |  Size: 5.2 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 3.8 KiB

After

Width:  |  Height:  |  Size: 5.2 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 6.9 KiB

After

Width:  |  Height:  |  Size: 9.7 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 2.3 KiB

After

Width:  |  Height:  |  Size: 3.0 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 6.1 KiB

After

Width:  |  Height:  |  Size: 8.5 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 6.1 KiB

After

Width:  |  Height:  |  Size: 8.5 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 11 KiB

After

Width:  |  Height:  |  Size: 16 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 67 KiB

After

Width:  |  Height:  |  Size: 419 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 11 KiB

After

Width:  |  Height:  |  Size: 16 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 18 KiB

After

Width:  |  Height:  |  Size: 29 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 5.5 KiB

After

Width:  |  Height:  |  Size: 7.9 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 15 KiB

After

Width:  |  Height:  |  Size: 23 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 16 KiB

After

Width:  |  Height:  |  Size: 26 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 66 KiB

After

Width:  |  Height:  |  Size: 406 KiB

+1 -1
View File
@@ -1,7 +1,7 @@
{ {
"$schema": "https://schema.tauri.app/config/2", "$schema": "https://schema.tauri.app/config/2",
"productName": "Guara", "productName": "Guara",
"version": "1.3.0", "version": "1.3.1",
"identifier": "dev.guara.app", "identifier": "dev.guara.app",
"build": { "build": {
"frontendDist": "../ui" "frontendDist": "../ui"
+3 -3
View File
@@ -332,7 +332,7 @@ dialog.lightbox[open] { display: grid; }
.lb-head .ttl { flex: 1; min-width: 0; } .lb-head .ttl b { display: block; white-space: nowrap; overflow: hidden; text-overflow: ellipsis; } .lb-head .ttl small { color: var(--text-2); } .lb-head .ttl { flex: 1; min-width: 0; } .lb-head .ttl b { display: block; white-space: nowrap; overflow: hidden; text-overflow: ellipsis; } .lb-head .ttl small { color: var(--text-2); }
.lb-body { padding: 12px; min-height: 0; } .lb-body { padding: 12px; min-height: 0; }
.hero-logo { width: min(440px, 80%); height: auto; display: block; margin: 0 0 22px -4px; } .hero-logo { width: min(340px, 70%); height: auto; margin: 0 0 14px -6px; }
.pill.accent { background: var(--accent-soft); color: var(--accent); } .pill.accent { background: var(--accent-soft); color: var(--accent); }
/* ------------------------------------------------------------ explorador de arquivos */ /* ------------------------------------------------------------ explorador de arquivos */
@@ -516,8 +516,8 @@ dialog.lightbox[open] { display: grid; }
.h-dot { display: inline-block; width: 9px; height: 9px; border-radius: 50%; background: var(--ok); } .h-dot { display: inline-block; width: 9px; height: 9px; border-radius: 50%; background: var(--ok); }
.h-dot.warning { background: var(--warn); } .h-dot.failing { background: var(--bad); } .h-dot.warning { background: var(--warn); } .h-dot.failing { background: var(--bad); }
/* logo inline: segue o tema escolhido no app, não o do sistema */ /* logo: uma arte só (laranja sobre transparente) serve aos temas claro e escuro */
.logo .a { stroke: var(--accent); } .logo .b { stroke: var(--accent-2); } .logo .t { fill: var(--text); } .logo-img { display: block; flex: none; }
/* atualização do app */ /* atualização do app */
.update-card { position: fixed; right: 18px; bottom: 18px; z-index: 60; width: min(400px, calc(100vw - 36px)); display: grid; gap: 10px; padding: 16px 18px; border-radius: 18px; background: var(--surface); box-shadow: var(--shadow); border: 1px solid color-mix(in srgb, var(--accent) 35%, transparent); } .update-card { position: fixed; right: 18px; bottom: 18px; z-index: 60; width: min(400px, calc(100vw - 36px)); display: grid; gap: 10px; padding: 16px 18px; border-radius: 18px; background: var(--surface); box-shadow: var(--shadow); border: 1px solid color-mix(in srgb, var(--accent) 35%, transparent); }
+1 -1
View File
@@ -265,7 +265,7 @@ function renderHome() {
S.device = null; S.job = null; S.device = null; S.job = null;
renderSide(); renderSide();
main.innerHTML = `<div class="page"> main.innerHTML = `<div class="page">
<section class="hero"><img class="hero-logo" src="guara-logo.svg" alt="Guará"><h1>Encontre o que você achou que tinha perdido.</h1> <section class="hero"><img class="logo-img hero-logo" src="guara.png" alt="Guará"><h1>Encontre o que você achou que tinha perdido.</h1>
<p>Escolha um disco, SSD ou pendrive ao lado. O Guará lê tudo: arquivos apagados, partições perdidas e espaço não particionado, sem escrever nada no disco de origem.</p></section> <p>Escolha um disco, SSD ou pendrive ao lado. O Guará lê tudo: arquivos apagados, partições perdidas e espaço não particionado, sem escrever nada no disco de origem.</p></section>
<div class="cards"> <div class="cards">
<div class="card"><h3>Uma varredura, tudo junto</h3><p>Metadados do sistema de arquivos e busca por assinatura na mesma passada, sem duplicatas.</p></div> <div class="card"><h3>Uma varredura, tudo junto</h3><p>Metadados do sistema de arquivos e busca por assinatura na mesma passada, sem duplicatas.</p></div>
-1
View File
@@ -1 +0,0 @@
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 100 100" role="img" aria-label="Guará"><style>.a{stroke:#0f766e}.b{stroke:#14b8a6}.t{fill:#1d1d1f}@media (prefers-color-scheme:dark){.a{stroke:#2dd4bf}.b{stroke:#5eead4}.t{fill:#f5f5f7}}</style><defs><clipPath id="g-head"><path d="M50 95 C46 88 43 80 40 74 C33 70 25 64 22 56 L14 6 L36 30 C40 28 45 27 50 27 C55 27 60 28 64 30 L86 6 L78 56 C75 64 67 70 60 74 C57 80 54 88 50 95 Z"/></clipPath></defs><g clip-path="url(#g-head)" fill="none" stroke-width="4.2"><path class="a" d="M50 93A7 7 0 0 1 50 107"/><path class="b" d="M50 93A7 7 0 0 0 50 107" stroke-dasharray="3 3" stroke-dashoffset="0"/><path class="a" d="M50 86A14 14 0 0 1 50 114"/><path class="b" d="M50 86A14 14 0 0 0 50 114" stroke-dasharray="6 4" stroke-dashoffset="3"/><path class="a" d="M50 79A21 21 0 0 1 50 121"/><path class="b" d="M50 79A21 21 0 0 0 50 121" stroke-dasharray="9 5" stroke-dashoffset="6"/><path class="a" d="M50 72A28 28 0 0 1 50 128"/><path class="b" d="M50 72A28 28 0 0 0 50 128" stroke-dasharray="3 6" stroke-dashoffset="9"/><path class="a" d="M50 65A35 35 0 0 1 50 135"/><path class="b" d="M50 65A35 35 0 0 0 50 135" stroke-dasharray="6 3" stroke-dashoffset="12"/><path class="a" d="M50 58A42 42 0 0 1 50 142"/><path class="b" d="M50 58A42 42 0 0 0 50 142" stroke-dasharray="9 4" stroke-dashoffset="15"/><path class="a" d="M50 51A49 49 0 0 1 50 149"/><path class="b" d="M50 51A49 49 0 0 0 50 149" stroke-dasharray="3 5" stroke-dashoffset="18"/><path class="a" d="M50 44A56 56 0 0 1 50 156"/><path class="b" d="M50 44A56 56 0 0 0 50 156" stroke-dasharray="6 6" stroke-dashoffset="21"/><path class="a" d="M50 37A63 63 0 0 1 50 163"/><path class="b" d="M50 37A63 63 0 0 0 50 163" stroke-dasharray="9 3" stroke-dashoffset="24"/><path class="a" d="M50 30A70 70 0 0 1 50 170"/><path class="b" d="M50 30A70 70 0 0 0 50 170" stroke-dasharray="3 4" stroke-dashoffset="27"/><path class="a" d="M50 23A77 77 0 0 1 50 177"/><path class="b" d="M50 23A77 77 0 0 0 50 177" stroke-dasharray="6 5" stroke-dashoffset="30"/><path class="a" d="M50 16A84 84 0 0 1 50 184"/><path class="b" d="M50 16A84 84 0 0 0 50 184" stroke-dasharray="9 6" stroke-dashoffset="33"/><path class="a" d="M50 9A91 91 0 0 1 50 191"/><path class="b" d="M50 9A91 91 0 0 0 50 191" stroke-dasharray="3 3" stroke-dashoffset="36"/><path class="a" d="M50 2A98 98 0 0 1 50 198"/><path class="b" d="M50 2A98 98 0 0 0 50 198" stroke-dasharray="6 4" stroke-dashoffset="39"/><rect class="t" stroke="none" x="0" y="74" width="100" height="30"/></g><path class="t" d="M37 50Q42 47 46 52Q41 53 37 50ZM63 50Q58 47 54 52Q59 53 63 50Z"/></svg>

Before

Width:  |  Height:  |  Size: 2.6 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 22 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 870 KiB

-1
View File
@@ -1 +0,0 @@
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 100 100" role="img" aria-label="Guará"><style>.a{stroke:#0f766e}.b{stroke:#14b8a6}.t{fill:#1d1d1f}@media (prefers-color-scheme:dark){.a{stroke:#2dd4bf}.b{stroke:#5eead4}.t{fill:#f5f5f7}}</style><defs><clipPath id="g-head"><path d="M50 95 C46 88 43 80 40 74 C33 70 25 64 22 56 L14 6 L36 30 C40 28 45 27 50 27 C55 27 60 28 64 30 L86 6 L78 56 C75 64 67 70 60 74 C57 80 54 88 50 95 Z"/></clipPath></defs><g clip-path="url(#g-head)" fill="none" stroke-width="4.2"><path class="a" d="M50 93A7 7 0 0 1 50 107"/><path class="b" d="M50 93A7 7 0 0 0 50 107" stroke-dasharray="3 3" stroke-dashoffset="0"/><path class="a" d="M50 86A14 14 0 0 1 50 114"/><path class="b" d="M50 86A14 14 0 0 0 50 114" stroke-dasharray="6 4" stroke-dashoffset="3"/><path class="a" d="M50 79A21 21 0 0 1 50 121"/><path class="b" d="M50 79A21 21 0 0 0 50 121" stroke-dasharray="9 5" stroke-dashoffset="6"/><path class="a" d="M50 72A28 28 0 0 1 50 128"/><path class="b" d="M50 72A28 28 0 0 0 50 128" stroke-dasharray="3 6" stroke-dashoffset="9"/><path class="a" d="M50 65A35 35 0 0 1 50 135"/><path class="b" d="M50 65A35 35 0 0 0 50 135" stroke-dasharray="6 3" stroke-dashoffset="12"/><path class="a" d="M50 58A42 42 0 0 1 50 142"/><path class="b" d="M50 58A42 42 0 0 0 50 142" stroke-dasharray="9 4" stroke-dashoffset="15"/><path class="a" d="M50 51A49 49 0 0 1 50 149"/><path class="b" d="M50 51A49 49 0 0 0 50 149" stroke-dasharray="3 5" stroke-dashoffset="18"/><path class="a" d="M50 44A56 56 0 0 1 50 156"/><path class="b" d="M50 44A56 56 0 0 0 50 156" stroke-dasharray="6 6" stroke-dashoffset="21"/><path class="a" d="M50 37A63 63 0 0 1 50 163"/><path class="b" d="M50 37A63 63 0 0 0 50 163" stroke-dasharray="9 3" stroke-dashoffset="24"/><path class="a" d="M50 30A70 70 0 0 1 50 170"/><path class="b" d="M50 30A70 70 0 0 0 50 170" stroke-dasharray="3 4" stroke-dashoffset="27"/><path class="a" d="M50 23A77 77 0 0 1 50 177"/><path class="b" d="M50 23A77 77 0 0 0 50 177" stroke-dasharray="6 5" stroke-dashoffset="30"/><path class="a" d="M50 16A84 84 0 0 1 50 184"/><path class="b" d="M50 16A84 84 0 0 0 50 184" stroke-dasharray="9 6" stroke-dashoffset="33"/><path class="a" d="M50 9A91 91 0 0 1 50 191"/><path class="b" d="M50 9A91 91 0 0 0 50 191" stroke-dasharray="3 3" stroke-dashoffset="36"/><path class="a" d="M50 2A98 98 0 0 1 50 198"/><path class="b" d="M50 2A98 98 0 0 0 50 198" stroke-dasharray="6 4" stroke-dashoffset="39"/><rect class="t" stroke="none" x="0" y="74" width="100" height="30"/></g><path class="t" d="M37 50Q42 47 46 52Q41 53 37 50ZM63 50Q58 47 54 52Q59 53 63 50Z"/></svg>

Before

Width:  |  Height:  |  Size: 2.6 KiB

+3 -3
View File
@@ -5,7 +5,7 @@
<meta name="viewport" content="width=device-width, initial-scale=1, viewport-fit=cover"> <meta name="viewport" content="width=device-width, initial-scale=1, viewport-fit=cover">
<meta name="color-scheme" content="light dark"> <meta name="color-scheme" content="light dark">
<title>Guará</title> <title>Guará</title>
<link rel="icon" href="guara.svg" type="image/svg+xml"> <link rel="icon" href="guara-s.png" type="image/png">
<link rel="stylesheet" href="app.css"> <link rel="stylesheet" href="app.css">
</head> </head>
<body> <body>
@@ -14,10 +14,10 @@
<button class="icon-btn" id="menuBtn" aria-label="Abrir menu" aria-expanded="false"> <button class="icon-btn" id="menuBtn" aria-label="Abrir menu" aria-expanded="false">
<svg viewBox="0 0 24 24" width="22" height="22"><path d="M4 7h16M4 12h16M4 17h16" stroke="currentColor" stroke-width="2" stroke-linecap="round" fill="none"/></svg> <svg viewBox="0 0 24 24" width="22" height="22"><path d="M4 7h16M4 12h16M4 17h16" stroke="currentColor" stroke-width="2" stroke-linecap="round" fill="none"/></svg>
</button> </button>
<svg class="logo" width="24" height="24" aria-hidden="true" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 100 100"><defs><clipPath id="g-head-top"><path d="M50 95 C46 88 43 80 40 74 C33 70 25 64 22 56 L14 6 L36 30 C40 28 45 27 50 27 C55 27 60 28 64 30 L86 6 L78 56 C75 64 67 70 60 74 C57 80 54 88 50 95 Z"/></clipPath></defs><g clip-path="url(#g-head-top)" fill="none" stroke-width="4.2"><path class="a" d="M50 93A7 7 0 0 1 50 107"/><path class="b" d="M50 93A7 7 0 0 0 50 107" stroke-dasharray="3 3" stroke-dashoffset="0"/><path class="a" d="M50 86A14 14 0 0 1 50 114"/><path class="b" d="M50 86A14 14 0 0 0 50 114" stroke-dasharray="6 4" stroke-dashoffset="3"/><path class="a" d="M50 79A21 21 0 0 1 50 121"/><path class="b" d="M50 79A21 21 0 0 0 50 121" stroke-dasharray="9 5" stroke-dashoffset="6"/><path class="a" d="M50 72A28 28 0 0 1 50 128"/><path class="b" d="M50 72A28 28 0 0 0 50 128" stroke-dasharray="3 6" stroke-dashoffset="9"/><path class="a" d="M50 65A35 35 0 0 1 50 135"/><path class="b" d="M50 65A35 35 0 0 0 50 135" stroke-dasharray="6 3" stroke-dashoffset="12"/><path class="a" d="M50 58A42 42 0 0 1 50 142"/><path class="b" d="M50 58A42 42 0 0 0 50 142" stroke-dasharray="9 4" stroke-dashoffset="15"/><path class="a" d="M50 51A49 49 0 0 1 50 149"/><path class="b" d="M50 51A49 49 0 0 0 50 149" stroke-dasharray="3 5" stroke-dashoffset="18"/><path class="a" d="M50 44A56 56 0 0 1 50 156"/><path class="b" d="M50 44A56 56 0 0 0 50 156" stroke-dasharray="6 6" stroke-dashoffset="21"/><path class="a" d="M50 37A63 63 0 0 1 50 163"/><path class="b" d="M50 37A63 63 0 0 0 50 163" stroke-dasharray="9 3" stroke-dashoffset="24"/><path class="a" d="M50 30A70 70 0 0 1 50 170"/><path class="b" d="M50 30A70 70 0 0 0 50 170" stroke-dasharray="3 4" stroke-dashoffset="27"/><path class="a" d="M50 23A77 77 0 0 1 50 177"/><path class="b" d="M50 23A77 77 0 0 0 50 177" stroke-dasharray="6 5" stroke-dashoffset="30"/><path class="a" d="M50 16A84 84 0 0 1 50 184"/><path class="b" d="M50 16A84 84 0 0 0 50 184" stroke-dasharray="9 6" stroke-dashoffset="33"/><path class="a" d="M50 9A91 91 0 0 1 50 191"/><path class="b" d="M50 9A91 91 0 0 0 50 191" stroke-dasharray="3 3" stroke-dashoffset="36"/><path class="a" d="M50 2A98 98 0 0 1 50 198"/><path class="b" d="M50 2A98 98 0 0 0 50 198" stroke-dasharray="6 4" stroke-dashoffset="39"/><rect class="t" stroke="none" x="0" y="74" width="100" height="30"/></g><path class="t" d="M37 50Q42 47 46 52Q41 53 37 50ZM63 50Q58 47 54 52Q59 53 63 50Z"/></svg><strong>Guará</strong> <img class="logo-img" src="guara-s.png" width="24" height="24" alt=""><strong>Guará</strong>
</header> </header>
<aside class="sidebar" id="sidebar" aria-label="Dispositivos e sessões"> <aside class="sidebar" id="sidebar" aria-label="Dispositivos e sessões">
<div class="brand"><svg class="logo" width="30" height="30" aria-hidden="true" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 100 100"><defs><clipPath id="g-head-side"><path d="M50 95 C46 88 43 80 40 74 C33 70 25 64 22 56 L14 6 L36 30 C40 28 45 27 50 27 C55 27 60 28 64 30 L86 6 L78 56 C75 64 67 70 60 74 C57 80 54 88 50 95 Z"/></clipPath></defs><g clip-path="url(#g-head-side)" fill="none" stroke-width="4.2"><path class="a" d="M50 93A7 7 0 0 1 50 107"/><path class="b" d="M50 93A7 7 0 0 0 50 107" stroke-dasharray="3 3" stroke-dashoffset="0"/><path class="a" d="M50 86A14 14 0 0 1 50 114"/><path class="b" d="M50 86A14 14 0 0 0 50 114" stroke-dasharray="6 4" stroke-dashoffset="3"/><path class="a" d="M50 79A21 21 0 0 1 50 121"/><path class="b" d="M50 79A21 21 0 0 0 50 121" stroke-dasharray="9 5" stroke-dashoffset="6"/><path class="a" d="M50 72A28 28 0 0 1 50 128"/><path class="b" d="M50 72A28 28 0 0 0 50 128" stroke-dasharray="3 6" stroke-dashoffset="9"/><path class="a" d="M50 65A35 35 0 0 1 50 135"/><path class="b" d="M50 65A35 35 0 0 0 50 135" stroke-dasharray="6 3" stroke-dashoffset="12"/><path class="a" d="M50 58A42 42 0 0 1 50 142"/><path class="b" d="M50 58A42 42 0 0 0 50 142" stroke-dasharray="9 4" stroke-dashoffset="15"/><path class="a" d="M50 51A49 49 0 0 1 50 149"/><path class="b" d="M50 51A49 49 0 0 0 50 149" stroke-dasharray="3 5" stroke-dashoffset="18"/><path class="a" d="M50 44A56 56 0 0 1 50 156"/><path class="b" d="M50 44A56 56 0 0 0 50 156" stroke-dasharray="6 6" stroke-dashoffset="21"/><path class="a" d="M50 37A63 63 0 0 1 50 163"/><path class="b" d="M50 37A63 63 0 0 0 50 163" stroke-dasharray="9 3" stroke-dashoffset="24"/><path class="a" d="M50 30A70 70 0 0 1 50 170"/><path class="b" d="M50 30A70 70 0 0 0 50 170" stroke-dasharray="3 4" stroke-dashoffset="27"/><path class="a" d="M50 23A77 77 0 0 1 50 177"/><path class="b" d="M50 23A77 77 0 0 0 50 177" stroke-dasharray="6 5" stroke-dashoffset="30"/><path class="a" d="M50 16A84 84 0 0 1 50 184"/><path class="b" d="M50 16A84 84 0 0 0 50 184" stroke-dasharray="9 6" stroke-dashoffset="33"/><path class="a" d="M50 9A91 91 0 0 1 50 191"/><path class="b" d="M50 9A91 91 0 0 0 50 191" stroke-dasharray="3 3" stroke-dashoffset="36"/><path class="a" d="M50 2A98 98 0 0 1 50 198"/><path class="b" d="M50 2A98 98 0 0 0 50 198" stroke-dasharray="6 4" stroke-dashoffset="39"/><rect class="t" stroke="none" x="0" y="74" width="100" height="30"/></g><path class="t" d="M37 50Q42 47 46 52Q41 53 37 50ZM63 50Q58 47 54 52Q59 53 63 50Z"/></svg><div><strong>Guará</strong><small>Recuperação de arquivos</small></div></div> <div class="brand"><img class="logo-img" src="guara-s.png" width="30" height="30" alt=""><div><strong>Guará</strong><small>Recuperação de arquivos</small></div></div>
<nav> <nav>
<div class="side-title">Dispositivos <button class="icon-btn small" id="refreshBtn" title="Atualizar lista" aria-label="Atualizar lista"><svg viewBox="0 0 24 24" width="16" height="16"><path d="M20 12a8 8 0 1 1-2.5-5.8M20 4v5h-5" stroke="currentColor" stroke-width="2" fill="none" stroke-linecap="round" stroke-linejoin="round"/></svg></button></div> <div class="side-title">Dispositivos <button class="icon-btn small" id="refreshBtn" title="Atualizar lista" aria-label="Atualizar lista"><svg viewBox="0 0 24 24" width="16" height="16"><path d="M20 12a8 8 0 1 1-2.5-5.8M20 4v5h-5" stroke="currentColor" stroke-width="2" fill="none" stroke-linecap="round" stroke-linejoin="round"/></svg></button></div>
<ul id="deviceList" class="list"></ul> <ul id="deviceList" class="list"></ul>
+7 -7
View File
@@ -12,9 +12,9 @@ const JS: &str = include_str!("../../../apps/gui/ui/app.js");
const PREVIEW_JS: &str = include_str!("../../../apps/gui/ui/preview.js"); const PREVIEW_JS: &str = include_str!("../../../apps/gui/ui/preview.js");
const I18N_JS: &str = include_str!("../../../apps/gui/ui/i18n.js"); const I18N_JS: &str = include_str!("../../../apps/gui/ui/i18n.js");
const I18N_EN_JS: &str = include_str!("../../../apps/gui/ui/i18n-en.js"); const I18N_EN_JS: &str = include_str!("../../../apps/gui/ui/i18n-en.js");
const LOGO: &str = include_str!("../../../apps/gui/ui/guara-logo.svg");
const EXPLORER_JS: &str = include_str!("../../../apps/gui/ui/explorer.js"); const EXPLORER_JS: &str = include_str!("../../../apps/gui/ui/explorer.js");
const ICON: &str = include_str!("../../../apps/gui/ui/guara.svg"); const LOGO: &[u8] = include_bytes!("../../../apps/gui/ui/guara.png");
const LOGO_S: &[u8] = include_bytes!("../../../apps/gui/ui/guara-s.png");
const PDF_JS: &str = include_str!("../../../apps/gui/ui/vendor/pdf.min.mjs"); const PDF_JS: &str = include_str!("../../../apps/gui/ui/vendor/pdf.min.mjs");
const PDF_WORKER: &str = include_str!("../../../apps/gui/ui/vendor/pdf.worker.min.mjs"); const PDF_WORKER: &str = include_str!("../../../apps/gui/ui/vendor/pdf.worker.min.mjs");
@@ -98,8 +98,11 @@ fn handle(req: Request, eng: &Engine, token: &str, hosts: &[String]) {
Response::from_string(I18N_EN_JS).with_header(ct("text/javascript; charset=utf-8")), Response::from_string(I18N_EN_JS).with_header(ct("text/javascript; charset=utf-8")),
); );
} }
(Method::Get, "/guara-logo.svg") => { (Method::Get, "/guara.png") => {
let _ = req.respond(Response::from_string(LOGO).with_header(ct("image/svg+xml"))); let _ = req.respond(Response::from_data(LOGO).with_header(ct("image/png")));
}
(Method::Get, "/guara-s.png") => {
let _ = req.respond(Response::from_data(LOGO_S).with_header(ct("image/png")));
} }
(Method::Get, "/explorer.js") => { (Method::Get, "/explorer.js") => {
let _ = req.respond( let _ = req.respond(
@@ -107,9 +110,6 @@ fn handle(req: Request, eng: &Engine, token: &str, hosts: &[String]) {
.with_header(ct("text/javascript; charset=utf-8")), .with_header(ct("text/javascript; charset=utf-8")),
); );
} }
(Method::Get, "/guara.svg") => {
let _ = req.respond(Response::from_string(ICON).with_header(ct("image/svg+xml")));
}
(Method::Get, "/vendor/pdf.min.mjs") => { (Method::Get, "/vendor/pdf.min.mjs") => {
let _ = req.respond( let _ = req.respond(
Response::from_string(PDF_JS).with_header(ct("text/javascript; charset=utf-8")), Response::from_string(PDF_JS).with_header(ct("text/javascript; charset=utf-8")),
+3
View File
@@ -11,6 +11,9 @@ set -euo pipefail
cache="$1"; shift cache="$1"; shift
pkgs=("$@") pkgs=("$@")
mkdir -p "$cache/partial" mkdir -p "$cache/partial"
# O apt roda como root e deixa arquivos (lock, .deb) que o usuário do runner não lê; sem devolver a
# posse, o actions/cache falha ao empacotar a pasta ("tar failed with exit code 2") e nunca grava.
trap 'sudo chown -R "$(id -u):$(id -g)" "$cache" 2>/dev/null || true; rm -f "$cache/lock"' EXIT
opts=(-o "Dir::Cache::archives=$cache" -y) opts=(-o "Dir::Cache::archives=$cache" -y)
# 1) com .deb em cache: instala direto, sem nem atualizar o índice do apt # 1) com .deb em cache: instala direto, sem nem atualizar o índice do apt
+50
View File
@@ -0,0 +1,50 @@
#!/usr/bin/env python3
"""Gera, a partir da logo oficial, os arquivos derivados usados no app e nos ícones.
A logo oficial é apps/gui/ui/guara.png (RGBA, fundo transparente, serve aos temas claro e escuro).
Ela não é alterada aqui. Saída:
apps/gui/ui/guara-s.png 128 px, recortada e quadrada (barra lateral e favicon)
apps/gui/src-tauri/icons/source.png 1024 px, a arte sobre o fundo escuro com cantos arredondados;
o CI e `npx @tauri-apps/cli icon` geram o resto dos ícones.
Uso: python3 scripts/gerar-logo.py
"""
import os
from PIL import Image, ImageDraw
RAIZ = os.path.join(os.path.dirname(os.path.abspath(__file__)), "..")
UI = os.path.join(RAIZ, "apps/gui/ui")
ICONES = os.path.join(RAIZ, "apps/gui/src-tauri/icons")
FUNDO_ICONE = (10, 16, 28) # o azul-noite do fundo da arte original
def recortar_quadrado(im, margem=0.04):
"""Recorta no que é visível (opacidade > 16, ignora resquícios) e centraliza num quadrado."""
box = im.getchannel("A").point(lambda v: 255 if v > 16 else 0).getbbox()
im = im.crop(box)
w, h = im.size
lado = round(max(w, h) * (1 + 2 * margem))
quadro = Image.new("RGBA", (lado, lado), (0, 0, 0, 0))
quadro.paste(im, ((lado - w) // 2, (lado - h) // 2), im)
return quadro
def main():
logo = recortar_quadrado(Image.open(os.path.join(UI, "guara.png")).convert("RGBA"))
logo.resize((128, 128), Image.LANCZOS).save(os.path.join(UI, "guara-s.png"), optimize=True)
print("guara-s.png")
lado = 1024
fundo = Image.new("RGBA", (lado, lado), FUNDO_ICONE + (255,))
arte = logo.resize((round(lado * 0.82),) * 2, Image.LANCZOS)
fundo.paste(arte, ((lado - arte.width) // 2, (lado - arte.height) // 2), arte)
mascara = Image.new("L", (lado, lado), 0)
ImageDraw.Draw(mascara).rounded_rectangle((0, 0, lado - 1, lado - 1), radius=round(lado * 0.2237), fill=255)
icone = Image.new("RGBA", (lado, lado), (0, 0, 0, 0))
icone.paste(fundo, (0, 0), mascara)
icone.save(os.path.join(ICONES, "source.png"), optimize=True)
print("icons/source.png")
if __name__ == "__main__":
main()
+6
View File
@@ -0,0 +1,6 @@
#!/usr/bin/env bash
# Liga o hook de pre-push do repositório (roda scripts/verificar.sh antes de cada push).
set -euo pipefail
cd "$(dirname "$0")/.."
git config core.hooksPath .githooks
echo "hook ligado: git push passa a rodar scripts/verificar.sh (desligue com: git config --unset core.hooksPath)"
-54
View File
@@ -1,54 +0,0 @@
#!/usr/bin/env python3
"""Gera a logo do Guará: a cabeça do lobo-guará, de frente, recortada das
trilhas de um disco.
As trilhas são arcos concêntricos com centro abaixo do focinho. Na metade
direita estão inteiras (dados recuperados) e na esquerda quebradas em
fragmentos (dados perdidos). Focinho e olhos usam a cor do texto. As cores
são as do app (apps/gui/ui/app.css): --accent e --accent-2 no tema claro e
seus equivalentes no escuro, trocados por prefers-color-scheme.
Uso: python3 scripts/make-logo.py [pasta] (padrão: apps/gui/ui)
Grava guara-logo.svg e guara.svg (mesma arte; o segundo é o ícone).
O PNG para os ícones do app (src-tauri/icons/source.png) sai desta arte
renderizada em 1024x1024.
"""
import os, sys
HEAD = ("M50 95 C46 88 43 80 40 74 C33 70 25 64 22 56 L14 6 L36 30 "
"C40 28 45 27 50 27 C55 27 60 28 64 30 L86 6 L78 56 "
"C75 64 67 70 60 74 C57 80 54 88 50 95 Z")
STYLE = (".a{stroke:#0f766e}.b{stroke:#14b8a6}.t{fill:#1d1d1f}"
"@media (prefers-color-scheme:dark){.a{stroke:#2dd4bf}.b{stroke:#5eead4}.t{fill:#f5f5f7}}")
def tracks():
out = []
for i, r in enumerate(range(7, 104, 7)):
top, bot = 100 - r, 100 + r
out.append(f'<path class="a" d="M50 {top}A{r} {r} 0 0 1 50 {bot}"/>')
dash = f"{3 + i % 3 * 3} {3 + (i * 5) % 4}"
out.append(f'<path class="b" d="M50 {top}A{r} {r} 0 0 0 50 {bot}" '
f'stroke-dasharray="{dash}" stroke-dashoffset="{i * 3}"/>')
return "".join(out)
def svg():
return (
'<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 100 100" role="img" aria-label="Guará">'
f'<style>{STYLE}</style>'
f'<defs><clipPath id="g-head"><path d="{HEAD}"/></clipPath></defs>'
f'<g clip-path="url(#g-head)" fill="none" stroke-width="4.2">{tracks()}'
# o focinho é a ponta da própria cabeça (recortada pelo mesmo contorno),
# então nenhuma trilha escapa pelas laterais
'<rect class="t" stroke="none" x="0" y="74" width="100" height="30"/></g>'
'<path class="t" d="M37 50Q42 47 46 52Q41 53 37 50ZM63 50Q58 47 54 52Q59 53 63 50Z"/>'
'</svg>\n'
)
if __name__ == "__main__":
out = sys.argv[1] if len(sys.argv) > 1 else "apps/gui/ui"
for name in ("guara-logo.svg", "guara.svg"):
with open(os.path.join(out, name), "w") as f:
f.write(svg())
+49
View File
@@ -0,0 +1,49 @@
#!/usr/bin/env bash
# Verificação local: roda o mesmo que o CI roda, antes de você dar push.
#
# scripts/verificar.sh rápido (~1 min): formatação, clippy, tradução, scripts, workflows
# scripts/verificar.sh --completo inclui os testes do workspace e o cargo audit
#
# O CI leva de 5 a 30 minutos por execução e roda em 3 sistemas; quase tudo que o faz falhar
# aparece aqui em segundos. Se isto passa, o CI só deve revelar o que é próprio dele (Windows,
# macOS, imagens baixadas, apt do runner).
set -uo pipefail
cd "$(dirname "$0")/.."
completo=0
[ "${1:-}" = "--completo" ] && completo=1
falhas=()
passo() { # passo "nome" comando...
local nome="$1"; shift
printf '\n\033[1m== %s\033[0m\n' "$nome"
if "$@"; then printf '\033[32mok\033[0m %s\n' "$nome"; else printf '\033[31mFALHOU\033[0m %s\n' "$nome"; falhas+=("$nome"); fi
}
passo "formatação (cargo fmt)" cargo fmt --all -- --check
# as mesmas flags do CI: avisos viram erro, inclusive nos testes
passo "clippy (workspace, todos os alvos)" env RUSTFLAGS="-D warnings" cargo clippy --workspace --all-targets
passo "cobertura da tradução da interface" node scripts/check-ui-i18n.mjs
passo "teste do latest.json" python3 -B scripts/test_make_latest_json.py
passo "sintaxe dos scripts bash" bash -c 'for f in scripts/*.sh .githooks/*; do bash -n "$f" || exit 1; done'
passo "workflows (YAML válido)" python3 -c "
import glob, yaml
for f in glob.glob('.github/workflows/*.yml'):
yaml.safe_load(open(f))
"
if [ -f apps/gui/src-tauri/Cargo.toml ] && pkg-config --exists webkit2gtk-4.1 2>/dev/null; then
passo "app desktop (cargo check)" env RUSTFLAGS="" cargo check --manifest-path apps/gui/src-tauri/Cargo.toml
else
printf '\n(app desktop: pulado, faltam as bibliotecas do WebKitGTK; o CI compila)\n'
fi
if [ "$completo" = 1 ]; then
passo "testes (cargo test --workspace)" cargo test --workspace
passo "auditoria de dependências (cargo audit)" cargo audit
fi
printf '\n'
if [ ${#falhas[@]} -eq 0 ]; then
printf '\033[32mtudo certo\033[0m: pode dar push.\n'
else
printf '\033[31mfalhou:\033[0m %s\n' "${falhas[*]}"
exit 1
fi