diff --git a/README.md b/README.md
index d3ce53a..76a3820 100644
--- a/README.md
+++ b/README.md
@@ -1,124 +1,372 @@
-# 🎀 Tutorial de criação de cyberdeck usando um celular antigo ✨
+# Termux Linux-Android Suite
-## O que é um cyberdeck? 💻🩷
+Transforme seu Android em um desktop Linux completo usando Termux + Termux-X11 com um script modular, interativo e biligue (PT-BR / EN).
-
+> **Creditos**: Este projeto e um fork do repositorio de [giovn-aguiar](https://github.com/giovn-aguiar/linux-android), que por sua vez e um fork do projeto original de [Lucas Aguiar](https://github.com/lucasaguiar-la/linux-android). Esta versao estende o conceito original para uma suite modular completa.
+---
+## Indice
+- [Recursos](#recursos)
+- [Tutorial de Instalacao](#tutorial-de-instalacao)
+- [Uso por Linha de Comando](#uso-por-linha-de-comando)
+- [Aplicativos Disponiveis](#aplicativos-disponiveis)
+- [Aplicativos Futuros](#aplicativos-futuros)
+- [Desktops Suportados](#desktops-suportados)
+- [Arquitetura do Projeto](#arquitetura-do-projeto)
+- [FAQ e Solucao de Problemas](#faq-e-solucao-de-problemas)
+- [Creditos e Licenca](#creditos-e-licenca)
-Cyberdecks são computadores portáteis personalizados inspirados em ficção científica, cultura hacker e estética cyberpunk.
-Normalmente são feitos reaproveitando hardware antigo, adicionando acessórios, modificações estéticas e sistemas Linux personalizados ✨
+---
-A ideia é transformar um dispositivo comum em algo único, funcional e com muita personalidade ♡
-
-Neste tutorial, vamos utilizar um celular Android antigo para criar um ambiente Linux completo usando o Termux, transformando o aparelho em um mini computador portátil 💿⚡
+## Recursos
-## O que você vai precisar 🧃
+- **Menu interativo no terminal** com submenus para cada funcionalidade
+- **Biligue** (Portugues / English) com deteccao automatica do idioma do sistema
+- **Instalacao modular** - instale, remova ou troque desktops e apps individualmente
+- **Catalogo de apps** editavel (`apps.conf`) organizado por categoria
+- **Configuracao de GPU** automatica (Adreno/Freedreno) ou manual
+- **Temas e personalizacao** - temas escuros, icones, fontes, wallpapers
+- **Wine/Hangover** para rodar apps Windows em ARM64
+- **Backup e restauracao** de todas as configuracoes
+- **Diagnostico** de integridade e visualizacao de logs
-Lembrando que aqui estou mostrando o que vou utilizar no cyberdeck que estou criando 🎀
-Mas o mais legal de cyberdecks é que literalmente não existe regra — você pode criar utilizando até uma TV Box no lugar do celular e adaptar tudo do seu jeito ♡
+---
-- Um celular ou tablet Android 📱
-- Powerbank 🔋
-- Teclado Bluetooth ou USB ⌨️
-- Mouse Bluetooth ou USB 🖱️
-- Hub USB 🌐
-- Aproximadamente 2GB livres 💾
-- Criatividade para personalizar seu cyberdeck 💻🩷✨
+## Tutorial de Instalacao
-# Projeto Android Linux - Termux
+### Pre-requisitos
-## Descrição
+1. **Termux** instalado (versao do [F-Droid](https://f-droid.org/packages/com.termux/) ou [GitHub](https://github.com/termux/termux-app/releases) - NAO use a versao da Play Store, ela esta desatualizada)
+2. **Termux-X11** instalado ([GitHub Releases](https://github.com/nicknisi/termux-x11/releases))
+3. Conexao com a internet
-Script de configuração automatizada para instalar e gerenciar um ambiente Linux completo no Termux.
+### Passo 1: Preparar o Termux
-## Recursos
+Abra o Termux e atualize os pacotes:
-- Detecção automática do dispositivo e GPU
-- Suporte a múltiplos ambientes desktop (XFCE4, LXQt, MATE, KDE)
-- Aceleração gráfica otimizada por GPU
-- Instalação simplificada e automatizada
-- Compatibilidade com smartphones e tablets
+```bash
+pkg update -y && pkg upgrade -y
+```
-## Ambientes Desktop Suportados
+### Passo 2: Instalar o Git
-| Desktop | Peso | Recomendação |
-|---------|------|--------------|
-| XFCE4 | Médio | Recomendado |
-| LXQt | Leve | Para dispositivos antigos |
-| MATE | Médio | Alternativa estável |
-| KDE | Pesado | Para dispositivos poderosos |
+```bash
+pkg install -y git
+```
-## Instalação
+### Passo 3: Clonar o projeto
-1. Instale o [Termux](https://f-droid.org/pt_BR/packages/com.termux/) do F-Droid
-2. Abra o Termux e dê permissões para acesso ao armazenamento do celular:
+```bash
+git clone https://github.com/eobarretooo/linux-android.git
+cd linux-android
```
-termux-setup-storage
+
+### Passo 4: Dar permissao de execucao
+
+```bash
+chmod +x script-termux.sh
```
-3. Desbloqueie o modo Desenvolvedor no seu aparelho
-4. Em 'Opções do Desenvolvedor' desabilite a opção 'Desativar restrições de processos filhos' (ou 'Disable child process restrictions')
-5. Instale o git:
+
+### Passo 5: Rodar o script
+
+```bash
+./script-termux.sh
```
-pkg install git
+
+Na primeira execucao, o script ira:
+
+1. Pedir para selecionar o **idioma** (Portugues ou English)
+2. Abrir o **menu principal** com todas as opcoes
+
+### Passo 6: Instalacao Completa (Opcao 1 do menu)
+
+Ao selecionar "Instalacao Completa", o script faz tudo automaticamente:
+
+| Etapa | O que acontece |
+|-------|----------------|
+| 1 | Prepara o ambiente e corrige pacotes pendentes |
+| 2 | Atualiza o sistema (`pkg update && upgrade`) |
+| 3 | Adiciona repositorios (`x11-repo`, `tur-repo`) |
+| 4 | Instala o servidor grafico (Termux-X11) |
+| 5 | Instala o desktop escolhido (XFCE4, LXQt, MATE ou KDE) |
+| 6 | Configura drivers de GPU |
+| 7 | Instala audio (PulseAudio) |
+| 8 | Instala apps e utilitarios basicos |
+| 9 | Configura Wine/Hangover (opcional) |
+| 10 | Cria scripts de start/stop/info |
+| 11 | Cria atalhos no desktop |
+
+### Passo 7: Iniciar o desktop
+
+Depois da instalacao, basta rodar:
+
+```bash
+~/start-linux.sh
```
-6. Clone este repositório:
+
+E abrir o app **Termux-X11** no seu celular para ver a interface grafica.
+
+Para parar:
+
+```bash
+~/stop-linux.sh
```
-git clone https://github.com/lucasaguiar-la/linux-android.git
+
+Para ver o diagnostico:
+
+```bash
+~/linux-info.sh
```
-7. Após execute:
+
+---
+
+## Uso por Linha de Comando
+
+Alem do menu interativo, voce pode usar flags para automatizar:
+
+```bash
+# Mostra ajuda
+./script-termux.sh --help
+
+# Forca idioma
+./script-termux.sh --lang en
+
+# Instalacao completa automatizada
+./script-termux.sh --install
+
+# Instala apenas um desktop especifico
+./script-termux.sh --desktop xfce4
+
+# Instala um app do catalogo
+./script-termux.sh --app firefox
```
-# Acessa a pasta clonada
-cd linux-android
-# Da permissões para executar o script
-chmod +X script-termux.sh
+---
+
+## Aplicativos Disponiveis
+
+Estes sao os apps que vem no catalogo (`apps.conf`) e podem ser instalados pelo menu:
+
+### Navegadores
+
+| App | Pacote | Descricao |
+|-----|--------|-----------|
+| Firefox | `firefox` | Navegador completo com suporte a extensoes |
+| Chromium | `chromium` | Navegador baseado no motor do Chrome |
+
+### Editores de Codigo
+
+| App | Pacote | Descricao |
+|-----|--------|-----------|
+| Code OSS | `code-oss` | VS Code open-source para Termux |
+| Neovim | `neovim` | Editor de texto avancado no terminal |
+| Nano | `nano` | Editor simples para terminal |
+| Micro | `micro` | Editor moderno para terminal com mouse |
+
+### Ferramentas de Desenvolvimento
+
+| App | Pacote | Descricao |
+|-----|--------|-----------|
+| Git | `git` | Controle de versao |
+| Python | `python` | Linguagem Python 3 + pip |
+| Node.js | `nodejs` | Runtime JavaScript + npm |
+| Clang | `clang` | Compilador C/C++ |
+| Rust | `rust` | Linguagem Rust + cargo |
+| Go | `golang` | Linguagem Go |
+| Ruby | `ruby` | Linguagem Ruby + gem |
+
+### Multimidia
+
+| App | Pacote | Descricao |
+|-----|--------|-----------|
+| VLC | `vlc` | Player de video e audio universal |
+| MPV | `mpv` | Player leve de video |
+| GIMP | `gimp` | Editor de imagens profissional |
+| FFmpeg | `ffmpeg` | Conversor e encoder de midia |
+
+### Utilitarios
+
+| App | Pacote | Descricao |
+|-----|--------|-----------|
+| Neofetch | `neofetch` | Mostra info do sistema com estilo |
+| htop | `htop` | Monitor de processos interativo |
+| tmux | `tmux` | Multiplexador de terminal |
+| Thunar | `thunar` | Gerenciador de arquivos grafico |
+| Ranger | `ranger` | Gerenciador de arquivos no terminal |
+| bat | `bat` | Substituto do `cat` com syntax highlight |
+| ripgrep | `ripgrep` | Busca rapida em arquivos (substituto do grep) |
+| fzf | `fzf` | Buscador fuzzy interativo |
+| zip/unzip | `zip unzip` | Compactador/descompactador ZIP |
+| tar | `tar` | Compactador/descompactador TAR |
+
+### Rede
+
+| App | Pacote | Descricao |
+|-----|--------|-----------|
+| curl | `curl` | Transferencia de dados via URL |
+| wget | `wget` | Download de arquivos |
+| OpenSSH | `openssh` | Cliente e servidor SSH |
+| Nmap | `nmap` | Scanner de rede e portas |
+| WoL | `wol` | Wake-on-LAN para ligar PCs remotamente |
+| iproute2 | `iproute2` | Ferramentas de rede (ip, ss, etc) |
+
+---
+
+## Aplicativos Futuros
+
+Estes apps ja funcionam ou tem potencial para funcionar bem no Termux com X11, e podem ser adicionados ao catalogo no futuro:
+
+### Produtividade e Escritorio
+
+| App | Pacote | Status | Notas |
+|-----|--------|--------|-------|
+| LibreOffice | `libreoffice` | Funcional | Suite de escritorio completa (pesado, ~500MB) |
+| Thunderbird | `thunderbird` | Funcional | Cliente de email |
+| Evince | `evince` | Funcional | Leitor de PDF leve |
+| Zathura | `zathura` | Funcional | Leitor de PDF minimalista |
+| Galculator | `galculator` | Funcional | Calculadora grafica |
+| Mousepad | `mousepad` | Funcional | Editor de texto simples (XFCE) |
+
+### Desenvolvimento
+
+| App | Pacote | Status | Notas |
+|-----|--------|--------|-------|
+| MariaDB | `mariadb` | Funcional | Banco de dados SQL |
+| PostgreSQL | `postgresql` | Funcional | Banco de dados avancado |
+| Redis | `redis` | Funcional | Cache e banco NoSQL |
+| SQLite | `sqlite` | Funcional | Banco de dados em arquivo |
+| PHP | `php` | Funcional | Linguagem web + composer |
+| Perl | `perl` | Funcional | Linguagem de script |
+| Lua | `lua54` | Funcional | Linguagem leve e rapida |
+| CMake | `cmake` | Funcional | Sistema de build |
+| Meson | `meson` | Funcional | Sistema de build moderno |
+| Docker (via proot) | N/A | Experimental | Precisa de proot-distro |
+
+### Multimidia (Futuro)
+
+| App | Pacote | Status | Notas |
+|-----|--------|--------|-------|
+| Inkscape | `inkscape` | Funcional | Editor de vetores SVG |
+| Audacity | N/A | Experimental | Editor de audio (precisa compilar) |
+| OBS Studio | N/A | Nao funcional | Precisa de GPU real e pipewire |
+| Blender | N/A | Nao funcional | Muito pesado para Android |
+| ImageMagick | `imagemagick` | Funcional | Manipulacao de imagens via CLI |
+
+### Rede e Seguranca
+
+| App | Pacote | Status | Notas |
+|-----|--------|--------|-------|
+| Wireshark (tshark) | `tshark` | Funcional | Analise de pacotes de rede (CLI) |
+| Hydra | `hydra` | Funcional | Teste de forca bruta |
+| John the Ripper | `john` | Funcional | Cracker de senhas |
+| Aircrack-ng | `aircrack-ng` | Funcional | Suite de auditoria WiFi |
+| Metasploit | N/A | Via proot | Framework de pentesting |
+| SQLMap | `python` + pip | Funcional | Teste de injecao SQL |
+| Nikto | `perl` + git | Funcional | Scanner de vulnerabilidades web |
+
+### Terminais e Shells
+
+| App | Pacote | Status | Notas |
+|-----|--------|--------|-------|
+| Zsh | `zsh` | Funcional | Shell avancado |
+| Fish | `fish` | Funcional | Shell amigavel com autocomplete |
+| Oh My Zsh | via curl | Funcional | Framework de configuracao do Zsh |
+| Starship | `starship` | Funcional | Prompt customizavel multi-shell |
+| Alacritty | `alacritty` | Funcional | Terminal acelerado por GPU |
+
+> **Como adicionar novos apps**: Edite o arquivo `apps.conf` seguindo o formato `categoria|Nome|pacote`. O app vai aparecer automaticamente no menu.
+
+---
+
+## Desktops Suportados
+
+| Desktop | Peso | Estabilidade | Recomendacao |
+|---------|------|-------------|--------------|
+| **XFCE4** | Leve (~150MB) | Muito estavel | Recomendado para todos |
+| **LXQt** | Muito leve (~120MB) | Estavel | Bom para dispositivos fracos |
+| **MATE** | Medio (~200MB) | Estavel | Para quem prefere estilo GNOME 2 |
+| **KDE Plasma** | Pesado (~400MB) | Experimental | Bonito mas pode travar em devices fracos |
+
+---
+
+## Arquitetura do Projeto
-# Executa o script de instalação
-./script-termux.sh
```
-8. Selecione o ambiente desktop desejado
-9. Aguarde a instalação ser concluída
-10. Rode o script:
+linux-android/
+|-- script-termux.sh # Ponto de entrada principal
+|-- apps.conf # Catalogo de apps editavel
+|-- lang/
+| |-- pt.sh # Strings em Portugues
+| |-- en.sh # Strings em English
+|-- lib/
+ |-- common.sh # Cores, logs, spinner, helpers
+ |-- i18n.sh # Sistema de traducao
+ |-- checks.sh # Validacoes de ambiente
+ |-- device.sh # Deteccao de hardware/GPU
+ |-- desktop.sh # Gerenciamento de desktops
+ |-- apps.sh # Instalacao de apps do catalogo
+ |-- wine.sh # Gerenciamento de Wine/Hangover
+ |-- themes.sh # Temas, icones, fontes, wallpapers
+ |-- scripts.sh # Geracao de start/stop/info scripts
+ |-- backup.sh # Backup e restauracao
+ |-- menu.sh # Sistema de menus interativos
```
-# Voltar para a home
-cd
-#Executa o script
-./start-linux.sh
-```
-11. Instale o [Termux X11](https://github.com/termux/termux-x11/releases/tag/nightly) para acessar a interface gráfica
-12. Abra o Termux X11 e o provedor gráfico já estará funcionando
+---
-## Detecção de Hardware
+## FAQ e Solucao de Problemas
-O script detecta automaticamente:
-- **Marca do dispositivo**: Samsung, Xiaomi, etc.
-- **GPU**: Adreno (Samsung/Qualcomm) ou genérica
-- **Driver gráfico**: Freedom ou Zink (compatibilidade)
+### "Tela preta ao abrir o Termux-X11"
-## Requisitos
+- Rode `~/stop-linux.sh` e depois `~/start-linux.sh` novamente
+- Se persistir, va em **Menu > GPU > Desativar aceleracao** e reinicie
-- Android 5.0+
-- Termux instalado
-- Termux: X11
-- ~2GB de espaço livre
-- Conexão com internet
+### "Termux-X11 nao abre / app nao instalado"
-## Notas
+- Instale o APK do Termux-X11 pelo [GitHub](https://github.com/nicknisi/termux-x11/releases)
+- O script instala o pacote `termux-x11` interno, mas o app Android precisa ser instalado manualmente
-- Use XFCE4 para melhor equilíbrio entre performance e funcionalidade
-- Dispositivos antigos: prefira LXQt
-- Dispositivos topo de linha: experimente KDE
-- Para executar automatizamente o `./start-linux.sh` toda vez que abrir o Termux, faça o seguinte:
-```
-nano ~/.bashrc
+### "Sem audio"
+
+- Va em **Menu > Audio > Reinstalar PulseAudio**
+- Depois rode `~/stop-linux.sh` e `~/start-linux.sh`
+
+### "Wine nao funciona"
-# Cole o conteúdo abaixo:
-./start-linux.sh
+- Wine/Hangover so funciona em dispositivos **ARM64 (aarch64)**
+- Rode `uname -m` para verificar sua arquitetura
+
+### "Erro de dpkg travado"
+
+- O script detecta isso automaticamente e espera ate 90 segundos
+- Se persistir, rode manualmente: `dpkg --configure -a`
+
+### "Quero adicionar um app novo"
+
+Edite o arquivo `apps.conf`:
+
+```
+# Formato: categoria|Nome|pacote
+utilities|Meu App|meu-pacote
```
-## Licença
+O app aparece automaticamente no menu na proxima execucao.
+
+### "Quero trocar de desktop"
+
+Va em **Menu > Configurar Desktop > Trocar ambiente** e selecione o novo. O anterior nao e removido automaticamente.
+
+---
+
+## Creditos e Licenca
+
+- **Projeto original**: [Lucas Aguiar - linux-android](https://github.com/lucasaguiar-la/linux-android)
+- **Fork intermediario**: [giovn-aguiar - linux-android](https://github.com/giovn-aguiar/linux-android)
+- **Versao modular**: Extensao com menus, i18n, catalogo de apps e sistema de backup
+- **Licenca**: MIT
+
+---
-MIT
+> Feito para quem quer um Linux de verdade no bolso.
diff --git a/apps.conf b/apps.conf
new file mode 100644
index 0000000..85374f0
--- /dev/null
+++ b/apps.conf
@@ -0,0 +1,48 @@
+# Catálogo de Aplicativos / Application Catalog
+# Formato: categoria|nome_exibicao|pacote_termux
+# Format: category|display_name|termux_package
+
+# Navegadores / Browsers
+browsers|Firefox|firefox
+browsers|Chromium|chromium
+
+# Editores / Editors
+editors|Code OSS (VS Code)|code-oss
+editors|Neovim|neovim
+editors|Nano|nano
+editors|Micro|micro
+
+# Ferramentas de Dev / Dev Tools
+devtools|Git|git
+devtools|Python|python
+devtools|Node.js|nodejs
+devtools|Clang (C/C++)|clang
+devtools|Rust|rust
+devtools|Go|golang
+devtools|Ruby|ruby
+
+# Multimídia / Multimedia
+multimedia|VLC|vlc
+multimedia|MPV|mpv
+multimedia|GIMP|gimp
+multimedia|FFmpeg|ffmpeg
+
+# Utilitários / Utilities
+utilities|Neofetch|neofetch
+utilities|htop|htop
+utilities|tmux|tmux
+utilities|Thunar (File Manager)|thunar
+utilities|Ranger (TUI File Manager)|ranger
+utilities|bat (cat replacement)|bat
+utilities|ripgrep|ripgrep
+utilities|fzf|fzf
+utilities|zip/unzip|zip unzip
+utilities|tar|tar
+
+# Rede / Network
+network|curl|curl
+network|wget|wget
+network|OpenSSH|openssh
+network|Nmap|nmap
+network|WoL|wol
+network|iproute2|iproute2
diff --git a/lang/en.sh b/lang/en.sh
new file mode 100644
index 0000000..f070101
--- /dev/null
+++ b/lang/en.sh
@@ -0,0 +1,233 @@
+# ===== General =====
+STRINGS[lang_name]="English"
+STRINGS[yes_chars]="y|yes|s|sim"
+STRINGS[no_chars]="n|no|nao|não"
+STRINGS[yes_letter]="y"
+STRINGS[no_letter]="n"
+STRINGS[yes_no_prompt]="y/n"
+STRINGS[invalid_option]="Invalid option. Try again."
+STRINGS[answer_yes_no]="Answer with y or n."
+STRINGS[press_enter]="Press ENTER to continue..."
+STRINGS[back]="Back"
+STRINGS[exit]="Exit"
+STRINGS[or]="or"
+
+# ===== Banner =====
+STRINGS[banner_title]="Configuring Termux Linux/X11"
+STRINGS[banner_status_desktop]="Desktop"
+STRINGS[banner_status_gpu]="GPU"
+STRINGS[banner_status_wine]="Wine"
+STRINGS[banner_status_status]="Status"
+STRINGS[status_running]="running"
+STRINGS[status_stopped]="stopped"
+STRINGS[status_installed]="installed"
+STRINGS[status_not_installed]="not installed"
+STRINGS[status_enabled]="enabled"
+STRINGS[status_disabled]="disabled"
+
+# ===== Logging =====
+STRINGS[install_log_at]="Installation log: %s"
+STRINGS[log_complete]="Full log: %s"
+STRINGS[last_log_lines]="Last log lines:"
+STRINGS[error_prefix]="ERROR"
+STRINGS[unexpected_error_line]="Unexpected ERROR at line %s: %s"
+STRINGS[step_completed]="Step %s/%s completed"
+STRINGS[failed_at]="Failed at: %s"
+STRINGS[attempt_failed]="Attempt %s/%s failed for %s. Retrying in %ss..."
+
+# ===== Installation =====
+STRINGS[installing]="Installing: %s"
+STRINGS[trying_install_optional]="Trying to install optional package: %s"
+STRINGS[installed]="Installed: %s"
+STRINGS[optional_pkg_failed]="Optional package unavailable or failed: %s"
+STRINGS[trying_install]="Trying to install %s: %s"
+STRINGS[no_option_available]="No option available to install: %s (%s)"
+STRINGS[already_installed]="Already installed: %s"
+STRINGS[not_installed]="Not installed: %s"
+
+# ===== Checks =====
+STRINGS[checking_internet]="Checking internet..."
+STRINGS[no_internet]="No internet connection or DNS unavailable."
+STRINGS[must_run_in_termux]="This script must be run inside regular Termux, not in Linux/PC/proot."
+STRINGS[pkg_not_found]="Command 'pkg' not found. Update/reinstall Termux."
+STRINGS[waiting_apt]="Waiting for another apt/dpkg process to finish..."
+STRINGS[apt_stuck]="Another apt/dpkg process has been stuck for too long. Close other Termux sessions and try again."
+
+# ===== Device =====
+STRINGS[architecture]="Architecture: %s"
+STRINGS[device_info]="Device: %s %s"
+STRINGS[wine_arm64_warning]="Wine/Hangover and GPU acceleration work best on ARM64/aarch64."
+
+# ===== GPU =====
+STRINGS[gpu_config_title]="GPU Configuration"
+STRINGS[gpu_auto]="Automatic (recommended)"
+STRINGS[gpu_force_adreno]="Force Adreno/Freedreno GPU acceleration"
+STRINGS[gpu_disable]="Disable GPU acceleration / use software"
+STRINGS[gpu_prompt]="Option [1-3, default=1]: "
+STRINGS[gpu_adreno_detected]="Qualcomm/Adreno GPU detected. Acceleration will be enabled."
+STRINGS[gpu_adreno_not_detected]="Adreno GPU not detected. Using compatible mode without forced acceleration."
+STRINGS[gpu_forced_warning]="GPU acceleration was forced. If the screen goes black/freezes, run again and choose option 3."
+STRINGS[gpu_disabled]="GPU acceleration disabled."
+STRINGS[gpu_base_installed]="Graphics base installed"
+STRINGS[gpu_base_install]="Installing Vulkan/Zink graphics base"
+STRINGS[gpu_base_failed]="mesa-zink/vulkan-loader-android drivers failed. Continuing in software mode."
+STRINGS[gpu_software_mode]="Software mode selected. Extra GPU drivers will not be forced."
+
+# ===== Desktop =====
+STRINGS[desktop_title]="Choose Desktop"
+STRINGS[desktop_xfce4]="XFCE4 (recommended/most stable)"
+STRINGS[desktop_lxqt]="LXQt (lightweight)"
+STRINGS[desktop_mate]="MATE (medium)"
+STRINGS[desktop_kde]="KDE Plasma (heavy/experimental)"
+STRINGS[desktop_prompt]="Option [1-4, default=1]: "
+STRINGS[desktop_chosen]="Desktop chosen: %s"
+STRINGS[desktop_command_not_found]="Command '%s' was not found after installing %s. Check the log and try another desktop."
+STRINGS[desktop_current]="Current desktop: %s"
+STRINGS[desktop_change]="Change desktop environment"
+STRINGS[desktop_reinstall]="Reinstall current desktop"
+STRINGS[desktop_remove]="Remove current desktop"
+STRINGS[desktop_view_status]="View installed desktop"
+STRINGS[desktop_remove_confirm]="Are you sure you want to remove %s? [y/N]: "
+STRINGS[desktop_removed]="Desktop %s removed."
+STRINGS[desktop_none_installed]="No desktop installed."
+STRINGS[desktop_config_title]="Configure Desktop"
+
+# ===== Apps =====
+STRINGS[apps_title]="Manage Applications"
+STRINGS[apps_browsers]="Browsers"
+STRINGS[apps_editors]="Code Editors"
+STRINGS[apps_devtools]="Dev Tools"
+STRINGS[apps_multimedia]="Multimedia"
+STRINGS[apps_utilities]="Utilities"
+STRINGS[apps_network]="Network"
+STRINGS[apps_install_all]="Install All"
+STRINGS[apps_install_category]="Install category: %s"
+STRINGS[apps_select_prompt]="Select apps (e.g.: 1 3 5 or 'all'): "
+STRINGS[apps_none_in_category]="No apps in this category."
+STRINGS[apps_basic_tools]="basic tools"
+
+# ===== Wine =====
+STRINGS[wine_title]="Manage Wine/Hangover"
+STRINGS[wine_install_prompt]="Install Wine/Hangover? [y/N]: "
+STRINGS[wine_not_arm64]="Your device doesn't appear to be ARM64/aarch64. Wine/Hangover may not work well."
+STRINGS[wine_shortcut_created]="Wine shortcut created."
+STRINGS[wine_not_complete]="Hangover Wine doesn't appear to be fully installed."
+STRINGS[wine_skipped]="Wine/Hangover skipped."
+STRINGS[wine_install]="Install Wine/Hangover"
+STRINGS[wine_remove]="Remove Wine/Hangover"
+STRINGS[wine_status]="Wine status"
+STRINGS[wine_remove_confirm]="Are you sure you want to remove Wine/Hangover? [y/N]: "
+STRINGS[wine_removed]="Wine/Hangover removed."
+STRINGS[wine_config_title]="Configure Wine/Hangover"
+
+# ===== Themes =====
+STRINGS[themes_title]="Themes & Personalization"
+STRINGS[themes_dark]="Install dark theme"
+STRINGS[themes_icons]="Install icon pack"
+STRINGS[themes_wallpaper]="Set wallpaper"
+STRINGS[themes_fonts]="Install fonts"
+STRINGS[themes_dracula]="Dracula"
+STRINGS[themes_nord]="Nord"
+STRINGS[themes_gruvbox]="Gruvbox"
+STRINGS[themes_arc_dark]="Arc Dark"
+STRINGS[themes_papirus]="Papirus"
+STRINGS[themes_adwaita]="Adwaita"
+STRINGS[themes_select_theme]="Select theme: "
+STRINGS[themes_select_icons]="Select icons: "
+STRINGS[themes_installed]="Theme %s installed."
+STRINGS[themes_icons_installed]="Icons %s installed."
+STRINGS[themes_fonts_installed]="Fonts installed."
+STRINGS[themes_wallpaper_set]="Wallpaper set."
+STRINGS[themes_wallpaper_path]="Wallpaper path: "
+STRINGS[themes_wallpaper_not_found]="Wallpaper file not found."
+
+# ===== Scripts =====
+STRINGS[creating_scripts]="Creating startup scripts"
+STRINGS[scripts_created]="Scripts created."
+STRINGS[creating_shortcuts]="Creating shortcuts"
+
+# ===== Backup =====
+STRINGS[backup_title]="Backup / Restore Config"
+STRINGS[backup_save]="Save current configuration"
+STRINGS[backup_restore]="Restore previous configuration"
+STRINGS[backup_export]="Export to external storage"
+STRINGS[backup_saved]="Configuration saved to: %s"
+STRINGS[backup_restored]="Configuration restored from: %s"
+STRINGS[backup_not_found]="No backup found."
+STRINGS[backup_exported]="Backup exported to: %s"
+STRINGS[backup_export_path]="/sdcard/termux-linux-backup"
+STRINGS[backup_list]="Available backups:"
+STRINGS[backup_select]="Select backup: "
+STRINGS[backup_config_loaded]="Previous configuration loaded: Desktop=%s, GPU=%s"
+
+# ===== Maintenance =====
+STRINGS[maint_title]="Maintenance & Diagnostics"
+STRINGS[maint_update]="Update system"
+STRINGS[maint_check_integrity]="Check installation integrity"
+STRINGS[maint_view_install_log]="View installation logs"
+STRINGS[maint_view_start_log]="View startup logs"
+STRINGS[maint_clean_cache]="Clean package cache"
+STRINGS[maint_diagnostics]="Run full diagnostics"
+STRINGS[maint_recreate_scripts]="Recreate start/stop scripts"
+STRINGS[maint_cache_cleaned]="Cache cleaned."
+STRINGS[maint_updating]="Updating system..."
+STRINGS[maint_updated]="System updated."
+STRINGS[maint_components_missing]="%s component(s) missing. Use the menu to reinstall."
+STRINGS[maint_all_ok]="All components are installed."
+STRINGS[maint_found]="found"
+STRINGS[maint_not_found]="NOT found"
+
+# ===== Main menu =====
+STRINGS[menu_title]="Main Menu"
+STRINGS[menu_full_install]="Full Installation"
+STRINGS[menu_apps]="Manage Applications"
+STRINGS[menu_desktop]="Configure Desktop"
+STRINGS[menu_gpu]="Configure GPU"
+STRINGS[menu_audio]="Configure Audio"
+STRINGS[menu_wine]="Manage Wine/Hangover"
+STRINGS[menu_themes]="Themes & Personalization"
+STRINGS[menu_maintenance]="Maintenance & Diagnostics"
+STRINGS[menu_backup]="Backup / Restore Config"
+STRINGS[menu_exit]="Exit"
+STRINGS[menu_prompt]="Choose an option: "
+STRINGS[menu_invalid]="Invalid option."
+STRINGS[menu_goodbye]="Goodbye!"
+
+# ===== Full install steps =====
+STRINGS[step_preparing]="Preparing environment"
+STRINGS[step_updating]="Updating system"
+STRINGS[step_adding_repos]="Adding repositories"
+STRINGS[step_graphics_server]="Installing graphics server"
+STRINGS[step_installing_desktop]="Installing %s"
+STRINGS[step_configuring_gpu]="Configuring GPU"
+STRINGS[step_installing_audio]="Installing audio"
+STRINGS[step_installing_apps]="Installing apps and utilities"
+STRINGS[step_configuring_wine]="Configuring Wine/Hangover"
+STRINGS[step_creating_scripts]="Creating startup scripts"
+STRINGS[step_creating_shortcuts]="Creating shortcuts"
+
+# ===== Completion =====
+STRINGS[install_complete]="INSTALLATION COMPLETE"
+STRINGS[install_desktop_label]="Desktop"
+STRINGS[install_gpu_label]="GPU"
+STRINGS[install_start_cmd]="Start"
+STRINGS[install_stop_cmd]="Stop"
+STRINGS[install_info_cmd]="Info"
+STRINGS[install_log_label]="Log"
+STRINGS[install_open_x11]="After starting, open the Termux-X11 app to see the interface."
+STRINGS[install_start_now]="Start the desktop now? [y/N]: "
+
+# ===== Audio =====
+STRINGS[audio_title]="Configure Audio"
+STRINGS[audio_install]="Install PulseAudio"
+STRINGS[audio_test]="Test audio"
+STRINGS[audio_restart]="Restart PulseAudio"
+STRINGS[audio_status]="PulseAudio status"
+STRINGS[audio_installed]="PulseAudio installed."
+STRINGS[audio_running]="PulseAudio is running."
+STRINGS[audio_not_running]="PulseAudio is not running."
+STRINGS[audio_restarted]="PulseAudio restarted."
+
+# ===== Language =====
+STRINGS[lang_title]="Selecione o idioma / Select language"
+STRINGS[lang_prompt]="Opção / Option [1-2]: "
diff --git a/lang/pt.sh b/lang/pt.sh
new file mode 100644
index 0000000..4e9fc4f
--- /dev/null
+++ b/lang/pt.sh
@@ -0,0 +1,233 @@
+# ===== Geral =====
+STRINGS[lang_name]="Português"
+STRINGS[yes_chars]="s|sim|y|yes"
+STRINGS[no_chars]="n|nao|não|no"
+STRINGS[yes_letter]="s"
+STRINGS[no_letter]="n"
+STRINGS[yes_no_prompt]="s/n"
+STRINGS[invalid_option]="Opção inválida. Tente novamente."
+STRINGS[answer_yes_no]="Responda com s ou n."
+STRINGS[press_enter]="Pressione ENTER para continuar..."
+STRINGS[back]="Voltar"
+STRINGS[exit]="Sair"
+STRINGS[or]="ou"
+
+# ===== Banner =====
+STRINGS[banner_title]="Configurando Termux Linux/X11"
+STRINGS[banner_status_desktop]="Desktop"
+STRINGS[banner_status_gpu]="GPU"
+STRINGS[banner_status_wine]="Wine"
+STRINGS[banner_status_status]="Status"
+STRINGS[status_running]="rodando"
+STRINGS[status_stopped]="parado"
+STRINGS[status_installed]="instalado"
+STRINGS[status_not_installed]="não instalado"
+STRINGS[status_enabled]="ativada"
+STRINGS[status_disabled]="desativada"
+
+# ===== Logging =====
+STRINGS[install_log_at]="Log da instalação: %s"
+STRINGS[log_complete]="Log completo: %s"
+STRINGS[last_log_lines]="Últimas linhas do log:"
+STRINGS[error_prefix]="ERRO"
+STRINGS[unexpected_error_line]="ERRO inesperado na linha %s: %s"
+STRINGS[step_completed]="Passo %s/%s concluído"
+STRINGS[failed_at]="Falha em: %s"
+STRINGS[attempt_failed]="Tentativa %s/%s falhou para %s. Retentando em %ss..."
+
+# ===== Instalação =====
+STRINGS[installing]="Instalando: %s"
+STRINGS[trying_install_optional]="Tentando instalar pacote opcional: %s"
+STRINGS[installed]="Instalado: %s"
+STRINGS[optional_pkg_failed]="Pacote opcional indisponível ou falhou: %s"
+STRINGS[trying_install]="Tentando instalar %s: %s"
+STRINGS[no_option_available]="Nenhuma opção disponível para instalar: %s (%s)"
+STRINGS[already_installed]="Já instalado: %s"
+STRINGS[not_installed]="Não instalado: %s"
+
+# ===== Verificações =====
+STRINGS[checking_internet]="Verificando internet..."
+STRINGS[no_internet]="Sem conexão com internet ou DNS indisponível."
+STRINGS[must_run_in_termux]="Este script deve ser executado dentro do Termux normal, não em Linux/PC/proot."
+STRINGS[pkg_not_found]="Comando 'pkg' não encontrado. Atualize/reinstale o Termux."
+STRINGS[waiting_apt]="Aguardando outro processo apt/dpkg terminar..."
+STRINGS[apt_stuck]="Outro processo do apt/dpkg está travado há muito tempo. Feche outros Termux e tente novamente."
+
+# ===== Dispositivo =====
+STRINGS[architecture]="Arquitetura: %s"
+STRINGS[device_info]="Dispositivo: %s %s"
+STRINGS[wine_arm64_warning]="Wine/Hangover e aceleração gráfica costumam funcionar melhor em ARM64/aarch64."
+
+# ===== GPU =====
+STRINGS[gpu_config_title]="Configuração de GPU"
+STRINGS[gpu_auto]="Automático (recomendado)"
+STRINGS[gpu_force_adreno]="Forçar aceleração GPU Adreno/Freedreno"
+STRINGS[gpu_disable]="Desativar aceleração GPU/usar software"
+STRINGS[gpu_prompt]="Opção [1-3, padrão=1]: "
+STRINGS[gpu_adreno_detected]="GPU Qualcomm/Adreno detectada. Aceleração será ativada."
+STRINGS[gpu_adreno_not_detected]="GPU Adreno não detectada. Usarei modo compatível sem aceleração forçada."
+STRINGS[gpu_forced_warning]="Aceleração GPU foi forçada. Se a tela ficar preta/travar, rode novamente e escolha a opção 3."
+STRINGS[gpu_disabled]="Aceleração GPU desativada."
+STRINGS[gpu_base_installed]="Base gráfica instalada"
+STRINGS[gpu_base_install]="Instalando base gráfica Vulkan/Zink"
+STRINGS[gpu_base_failed]="Drivers mesa-zink/vulkan-loader-android falharam. Vou continuar em modo software."
+STRINGS[gpu_software_mode]="Modo software selecionado. Drivers GPU extras não serão forçados."
+
+# ===== Desktop =====
+STRINGS[desktop_title]="Escolha o Desktop"
+STRINGS[desktop_xfce4]="XFCE4 (recomendado/mais estável)"
+STRINGS[desktop_lxqt]="LXQt (leve)"
+STRINGS[desktop_mate]="MATE (médio)"
+STRINGS[desktop_kde]="KDE Plasma (pesado/experimental)"
+STRINGS[desktop_prompt]="Opção [1-4, padrão=1]: "
+STRINGS[desktop_chosen]="Desktop escolhido: %s"
+STRINGS[desktop_command_not_found]="O comando '%s' não foi encontrado após instalar %s. Veja o log e tente outro desktop."
+STRINGS[desktop_current]="Desktop atual: %s"
+STRINGS[desktop_change]="Trocar ambiente desktop"
+STRINGS[desktop_reinstall]="Reinstalar desktop atual"
+STRINGS[desktop_remove]="Remover desktop atual"
+STRINGS[desktop_view_status]="Ver desktop instalado"
+STRINGS[desktop_remove_confirm]="Tem certeza que deseja remover %s? [s/N]: "
+STRINGS[desktop_removed]="Desktop %s removido."
+STRINGS[desktop_none_installed]="Nenhum desktop instalado."
+STRINGS[desktop_config_title]="Configurar Desktop"
+
+# ===== Aplicativos =====
+STRINGS[apps_title]="Gerenciar Aplicativos"
+STRINGS[apps_browsers]="Navegadores"
+STRINGS[apps_editors]="Editores de Código"
+STRINGS[apps_devtools]="Ferramentas de Dev"
+STRINGS[apps_multimedia]="Multimídia"
+STRINGS[apps_utilities]="Utilitários"
+STRINGS[apps_network]="Rede"
+STRINGS[apps_install_all]="Instalar Todos"
+STRINGS[apps_install_category]="Instalar categoria: %s"
+STRINGS[apps_select_prompt]="Selecione os apps (ex: 1 3 5 ou 'todos'): "
+STRINGS[apps_none_in_category]="Nenhum app nesta categoria."
+STRINGS[apps_basic_tools]="ferramentas básicas"
+
+# ===== Wine =====
+STRINGS[wine_title]="Gerenciar Wine/Hangover"
+STRINGS[wine_install_prompt]="Instalar Wine/Hangover? [s/N]: "
+STRINGS[wine_not_arm64]="Seu aparelho não parece ser ARM64/aarch64. Wine/Hangover pode não funcionar bem."
+STRINGS[wine_shortcut_created]="Atalho 'wine' criado."
+STRINGS[wine_not_complete]="Hangover Wine não parece ter sido instalado completamente."
+STRINGS[wine_skipped]="Wine/Hangover ignorado."
+STRINGS[wine_install]="Instalar Wine/Hangover"
+STRINGS[wine_remove]="Remover Wine/Hangover"
+STRINGS[wine_status]="Status do Wine"
+STRINGS[wine_remove_confirm]="Tem certeza que deseja remover Wine/Hangover? [s/N]: "
+STRINGS[wine_removed]="Wine/Hangover removido."
+STRINGS[wine_config_title]="Configurar Wine/Hangover"
+
+# ===== Temas =====
+STRINGS[themes_title]="Temas e Personalização"
+STRINGS[themes_dark]="Instalar tema escuro"
+STRINGS[themes_icons]="Instalar pacote de ícones"
+STRINGS[themes_wallpaper]="Definir wallpaper"
+STRINGS[themes_fonts]="Instalar fontes"
+STRINGS[themes_dracula]="Dracula"
+STRINGS[themes_nord]="Nord"
+STRINGS[themes_gruvbox]="Gruvbox"
+STRINGS[themes_arc_dark]="Arc Dark"
+STRINGS[themes_papirus]="Papirus"
+STRINGS[themes_adwaita]="Adwaita"
+STRINGS[themes_select_theme]="Selecione o tema: "
+STRINGS[themes_select_icons]="Selecione os ícones: "
+STRINGS[themes_installed]="Tema %s instalado."
+STRINGS[themes_icons_installed]="Ícones %s instalados."
+STRINGS[themes_fonts_installed]="Fontes instaladas."
+STRINGS[themes_wallpaper_set]="Wallpaper definido."
+STRINGS[themes_wallpaper_path]="Caminho do wallpaper: "
+STRINGS[themes_wallpaper_not_found]="Arquivo de wallpaper não encontrado."
+
+# ===== Scripts =====
+STRINGS[creating_scripts]="Criando scripts de inicialização"
+STRINGS[scripts_created]="Scripts criados."
+STRINGS[creating_shortcuts]="Criando atalhos"
+
+# ===== Backup =====
+STRINGS[backup_title]="Backup / Restaurar Config"
+STRINGS[backup_save]="Salvar configuração atual"
+STRINGS[backup_restore]="Restaurar configuração anterior"
+STRINGS[backup_export]="Exportar para armazenamento externo"
+STRINGS[backup_saved]="Configuração salva em: %s"
+STRINGS[backup_restored]="Configuração restaurada de: %s"
+STRINGS[backup_not_found]="Nenhum backup encontrado."
+STRINGS[backup_exported]="Backup exportado para: %s"
+STRINGS[backup_export_path]="/sdcard/termux-linux-backup"
+STRINGS[backup_list]="Backups disponíveis:"
+STRINGS[backup_select]="Selecione o backup: "
+STRINGS[backup_config_loaded]="Configuração anterior carregada: Desktop=%s, GPU=%s"
+
+# ===== Manutenção =====
+STRINGS[maint_title]="Manutenção e Diagnóstico"
+STRINGS[maint_update]="Atualizar sistema"
+STRINGS[maint_check_integrity]="Verificar integridade da instalação"
+STRINGS[maint_view_install_log]="Ver logs de instalação"
+STRINGS[maint_view_start_log]="Ver logs de inicialização"
+STRINGS[maint_clean_cache]="Limpar cache de pacotes"
+STRINGS[maint_diagnostics]="Executar diagnóstico completo"
+STRINGS[maint_recreate_scripts]="Recriar scripts de start/stop"
+STRINGS[maint_cache_cleaned]="Cache limpo."
+STRINGS[maint_updating]="Atualizando sistema..."
+STRINGS[maint_updated]="Sistema atualizado."
+STRINGS[maint_components_missing]="%s componente(s) ausente(s). Use o menu para reinstalar."
+STRINGS[maint_all_ok]="Todos os componentes estão instalados."
+STRINGS[maint_found]="encontrado"
+STRINGS[maint_not_found]="NÃO encontrado"
+
+# ===== Menu principal =====
+STRINGS[menu_title]="Menu Principal"
+STRINGS[menu_full_install]="Instalação Completa"
+STRINGS[menu_apps]="Gerenciar Aplicativos"
+STRINGS[menu_desktop]="Configurar Desktop"
+STRINGS[menu_gpu]="Configurar GPU"
+STRINGS[menu_audio]="Configurar Áudio"
+STRINGS[menu_wine]="Gerenciar Wine/Hangover"
+STRINGS[menu_themes]="Temas e Personalização"
+STRINGS[menu_maintenance]="Manutenção e Diagnóstico"
+STRINGS[menu_backup]="Backup / Restaurar Config"
+STRINGS[menu_exit]="Sair"
+STRINGS[menu_prompt]="Escolha uma opção: "
+STRINGS[menu_invalid]="Opção inválida."
+STRINGS[menu_goodbye]="Ate mais!"
+
+# ===== Instalação completa (passos) =====
+STRINGS[step_preparing]="Preparando ambiente"
+STRINGS[step_updating]="Atualizando sistema"
+STRINGS[step_adding_repos]="Adicionando repositórios"
+STRINGS[step_graphics_server]="Instalando servidor gráfico"
+STRINGS[step_installing_desktop]="Instalando %s"
+STRINGS[step_configuring_gpu]="Configurando GPU"
+STRINGS[step_installing_audio]="Instalando áudio"
+STRINGS[step_installing_apps]="Instalando apps e utilitários"
+STRINGS[step_configuring_wine]="Configurando Wine/Hangover"
+STRINGS[step_creating_scripts]="Criando scripts de inicialização"
+STRINGS[step_creating_shortcuts]="Criando atalhos"
+
+# ===== Conclusão =====
+STRINGS[install_complete]="INSTALAÇÃO CONCLUÍDA"
+STRINGS[install_desktop_label]="Desktop"
+STRINGS[install_gpu_label]="GPU"
+STRINGS[install_start_cmd]="Iniciar"
+STRINGS[install_stop_cmd]="Parar"
+STRINGS[install_info_cmd]="Info"
+STRINGS[install_log_label]="Log"
+STRINGS[install_open_x11]="Depois de iniciar, abra o app Termux-X11 para ver a interface."
+STRINGS[install_start_now]="Deseja iniciar o desktop agora? [s/N]: "
+
+# ===== Áudio =====
+STRINGS[audio_title]="Configurar Áudio"
+STRINGS[audio_install]="Instalar PulseAudio"
+STRINGS[audio_test]="Testar áudio"
+STRINGS[audio_restart]="Reiniciar PulseAudio"
+STRINGS[audio_status]="Status do PulseAudio"
+STRINGS[audio_installed]="PulseAudio instalado."
+STRINGS[audio_running]="PulseAudio está rodando."
+STRINGS[audio_not_running]="PulseAudio não está rodando."
+STRINGS[audio_restarted]="PulseAudio reiniciado."
+
+# ===== Idioma =====
+STRINGS[lang_title]="Selecione o idioma / Select language"
+STRINGS[lang_prompt]="Opção / Option [1-2]: "
diff --git a/lib/apps.sh b/lib/apps.sh
new file mode 100644
index 0000000..4988719
--- /dev/null
+++ b/lib/apps.sh
@@ -0,0 +1,164 @@
+#!/data/data/com.termux/files/usr/bin/bash
+# lib/apps.sh — Gerenciamento de aplicativos via catalogo
+# Sourced by script-termux.sh — NAO executar diretamente.
+
+# Categorias suportadas (devem coincidir com apps.conf)
+APP_CATEGORIES=("browsers" "editors" "devtools" "multimedia" "utilities" "network")
+
+# Mapeia categoria -> chave de traducao
+declare -gA APP_CAT_KEYS
+APP_CAT_KEYS[browsers]="apps_browsers"
+APP_CAT_KEYS[editors]="apps_editors"
+APP_CAT_KEYS[devtools]="apps_devtools"
+APP_CAT_KEYS[multimedia]="apps_multimedia"
+APP_CAT_KEYS[utilities]="apps_utilities"
+APP_CAT_KEYS[network]="apps_network"
+
+# Le apps de uma categoria do apps.conf
+# Retorna linhas no formato: nome_exibicao|pacote
+get_apps_in_category() {
+ local category="$1"
+ local conf_file="${SCRIPT_DIR}/apps.conf"
+
+ if [ ! -f "$conf_file" ]; then
+ return 0
+ fi
+
+ local grep_out=""
+ grep_out="$(grep "^${category}|" "$conf_file" 2>/dev/null || true)"
+ if [ -n "$grep_out" ]; then
+ echo "$grep_out" | while IFS='|' read -r _cat name pkg; do
+ printf '%s|%s\n' "$name" "$pkg"
+ done
+ fi
+}
+
+# Lista apps de uma categoria com status de instalacao
+list_category_apps() {
+ local category="$1"
+ local index=1
+
+ while IFS='|' read -r name pkg; do
+ local first_pkg=""
+ first_pkg="$(echo "$pkg" | awk '{print $1}')"
+ if is_pkg_installed "$first_pkg"; then
+ printf " %s[x]%s %2d) %s\n" "$GREEN" "$RESET" "$index" "$name"
+ else
+ printf " %s[ ]%s %2d) %s\n" "$DIM" "$RESET" "$index" "$name"
+ fi
+ index=$((index + 1))
+ done < <(get_apps_in_category "$category")
+}
+
+# Instala app(s) de uma categoria por indice
+install_category_app() {
+ local category="$1"
+ local indices="$2"
+ local apps=()
+
+ # Coleta todos os apps da categoria
+ while IFS='|' read -r name pkg; do
+ apps+=("$name|$pkg")
+ done < <(get_apps_in_category "$category")
+
+ if [ "${#apps[@]}" -eq 0 ]; then
+ warn "$(t apps_none_in_category)"
+ return 0
+ fi
+
+ # Se 'all' ou 'todos', instala todos
+ if [[ "$indices" == "all" ]] || [[ "$indices" == "todos" ]]; then
+ for entry in "${apps[@]}"; do
+ local name="${entry%%|*}"
+ local pkg="${entry#*|}"
+ info "$(t installing "$name")"
+ # shellcheck disable=SC2086
+ install_with_retry $pkg || warn "$(t optional_pkg_failed "$name")"
+ done
+ return 0
+ fi
+
+ # Instala por indices selecionados
+ local idx=""
+ for idx in $indices; do
+ if [[ "$idx" =~ ^[0-9]+$ ]] && [ "$idx" -ge 1 ] && [ "$idx" -le "${#apps[@]}" ]; then
+ local entry="${apps[$((idx - 1))]}"
+ local name="${entry%%|*}"
+ local pkg="${entry#*|}"
+ info "$(t installing "$name")"
+ # shellcheck disable=SC2086
+ install_with_retry $pkg || warn "$(t optional_pkg_failed "$name")"
+ else
+ warn "$(t invalid_option): $idx"
+ fi
+ done
+}
+
+# Submenu de uma categoria
+category_submenu() {
+ local category="$1"
+ local cat_name=""
+ cat_name="$(t "${APP_CAT_KEYS[$category]}")"
+
+ echo ""
+ echo " -- $cat_name --"
+ echo ""
+ list_category_apps "$category"
+ echo ""
+
+ local selection=""
+ read -r -p " $(t apps_select_prompt)" selection || selection=""
+
+ if [ -n "$selection" ]; then
+ install_category_app "$category" "$selection"
+ fi
+}
+
+# Menu principal de aplicativos
+apps_menu() {
+ while true; do
+ echo ""
+ _header "$(t apps_title)"
+
+ local i=1
+ for cat in "${APP_CATEGORIES[@]}"; do
+ local cat_name=""
+ cat_name="$(t "${APP_CAT_KEYS[$cat]}")"
+ _item "$i" "$cat_name"
+ i=$((i + 1))
+ done
+
+ _item "7" "$(t apps_install_all)"
+ _item "0" "$(t back)"
+ _footer
+ echo ""
+
+ local choice=""
+ read -r -p " $(t menu_prompt)" choice || choice="0"
+
+ case "$choice" in
+ [1-6])
+ local cat_index=$((choice - 1))
+ if [ "$cat_index" -lt "${#APP_CATEGORIES[@]}" ]; then
+ category_submenu "${APP_CATEGORIES[$cat_index]}"
+ fi
+ ;;
+ 7)
+ info "$(t apps_install_all)..."
+ for cat in "${APP_CATEGORIES[@]}"; do
+ install_category_app "$cat" "all"
+ done
+ ;;
+ 0) return ;;
+ *) warn "$(t menu_invalid)" ;;
+ esac
+
+ pause_prompt
+ done
+}
+
+# Instalacao de apps basicos (usado na instalacao completa)
+install_basic_apps() {
+ install_required "$(t apps_basic_tools)" git wget curl python nano tar unzip zip openssl
+ install_optional_packages neofetch vlc firefox code-oss wol
+}
diff --git a/lib/backup.sh b/lib/backup.sh
new file mode 100644
index 0000000..3066b4e
--- /dev/null
+++ b/lib/backup.sh
@@ -0,0 +1,153 @@
+#!/data/data/com.termux/files/usr/bin/bash
+# lib/backup.sh — Backup e restauração de configuração
+# Sourced by script-termux.sh — NÃO executar diretamente.
+
+BACKUP_DIR="${STATE_DIR}/backups"
+
+backup_save() {
+ mkdir -p "$BACKUP_DIR"
+
+ local timestamp=""
+ timestamp="$(date '+%Y%m%d_%H%M%S')"
+ local backup_path="${BACKUP_DIR}/backup_${timestamp}"
+ mkdir -p "$backup_path"
+
+ # Salva config atual
+ if [ -f "${STATE_DIR}/config.env" ]; then
+ cp "${STATE_DIR}/config.env" "$backup_path/"
+ fi
+
+ # Salva scripts gerados
+ for script in start-linux.sh stop-linux.sh linux-info.sh; do
+ if [ -f "${HOME}/${script}" ]; then
+ cp "${HOME}/${script}" "$backup_path/"
+ fi
+ done
+
+ # Salva configurações de desktop (XFCE4)
+ if [ -d "${HOME}/.config/xfce4" ]; then
+ cp -r "${HOME}/.config/xfce4" "$backup_path/" 2>/dev/null || true
+ fi
+
+ # Salva configurações de Termux
+ if [ -d "${HOME}/.termux" ]; then
+ cp -r "${HOME}/.termux" "$backup_path/dot-termux" 2>/dev/null || true
+ fi
+
+ ok "$(t backup_saved "$backup_path")"
+}
+
+backup_restore() {
+ if [ ! -d "$BACKUP_DIR" ] || [ -z "$(ls -A "$BACKUP_DIR" 2>/dev/null)" ]; then
+ warn "$(t backup_not_found)"
+ return 1
+ fi
+
+ echo ""
+ echo " $(t backup_list)"
+ echo ""
+
+ local backups=()
+ local i=1
+ local dir=""
+
+ for dir in "$BACKUP_DIR"/backup_*; do
+ if [ -d "$dir" ]; then
+ local name=""
+ name="$(basename "$dir")"
+ backups+=("$dir")
+ printf " %d) %s\n" "$i" "$name"
+ i=$((i + 1))
+ fi
+ done
+
+ if [ "${#backups[@]}" -eq 0 ]; then
+ warn "$(t backup_not_found)"
+ return 1
+ fi
+
+ echo ""
+ local choice=""
+ read -r -p " $(t backup_select)" choice || return
+
+ if [[ "$choice" =~ ^[0-9]+$ ]] && [ "$choice" -ge 1 ] && [ "$choice" -le "${#backups[@]}" ]; then
+ local selected="${backups[$((choice - 1))]}"
+
+ # Restaura config.env
+ if [ -f "$selected/config.env" ]; then
+ cp "$selected/config.env" "${STATE_DIR}/"
+ load_config
+ fi
+
+ # Restaura scripts
+ for script in start-linux.sh stop-linux.sh linux-info.sh; do
+ if [ -f "$selected/$script" ]; then
+ cp "$selected/$script" "${HOME}/"
+ chmod +x "${HOME}/${script}"
+ fi
+ done
+
+ # Restaura configs de desktop
+ if [ -d "$selected/xfce4" ]; then
+ mkdir -p "${HOME}/.config"
+ cp -r "$selected/xfce4" "${HOME}/.config/" 2>/dev/null || true
+ fi
+
+ # Restaura configs de Termux
+ if [ -d "$selected/dot-termux" ]; then
+ cp -r "$selected/dot-termux" "${HOME}/.termux" 2>/dev/null || true
+ fi
+
+ ok "$(t backup_restored "$selected")"
+ else
+ warn "$(t invalid_option)"
+ fi
+}
+
+backup_export() {
+ local export_dir=""
+ export_dir="$(t backup_export_path)"
+ mkdir -p "$export_dir"
+
+ local timestamp=""
+ timestamp="$(date '+%Y%m%d_%H%M%S')"
+ local export_file="${export_dir}/termux-linux-backup_${timestamp}.tar.gz"
+
+ if [ -d "$STATE_DIR" ]; then
+ tar -czf "$export_file" -C "$HOME" \
+ ".termux-linux" \
+ "start-linux.sh" \
+ "stop-linux.sh" \
+ "linux-info.sh" \
+ 2>/dev/null || true
+ ok "$(t backup_exported "$export_file")"
+ else
+ warn "$(t backup_not_found)"
+ fi
+}
+
+backup_menu() {
+ while true; do
+ echo ""
+ _header "$(t backup_title)"
+ _item "1" "$(t backup_save)"
+ _item "2" "$(t backup_restore)"
+ _item "3" "$(t backup_export)"
+ _item "0" "$(t back)"
+ _footer
+ echo ""
+
+ local choice=""
+ read -r -p " $(t menu_prompt)" choice || choice="0"
+
+ case "$choice" in
+ 1) backup_save ;;
+ 2) backup_restore ;;
+ 3) backup_export ;;
+ 0) return ;;
+ *) warn "$(t menu_invalid)" ;;
+ esac
+
+ pause_prompt
+ done
+}
diff --git a/lib/checks.sh b/lib/checks.sh
new file mode 100644
index 0000000..623b26b
--- /dev/null
+++ b/lib/checks.sh
@@ -0,0 +1,37 @@
+#!/data/data/com.termux/files/usr/bin/bash
+# lib/checks.sh — Verificações de sistema
+# Sourced by script-termux.sh — NÃO executar diretamente.
+
+require_termux() {
+ if [ "${PREFIX:-}" != "/data/data/com.termux/files/usr" ]; then
+ die "$(t must_run_in_termux)"
+ fi
+
+ command_exists pkg || die "$(t pkg_not_found)"
+}
+
+check_internet() {
+ if command_exists curl; then
+ curl -fsI --connect-timeout 12 https://packages.termux.dev >/dev/null 2>>"$LOG" && return 0
+ curl -fsI --connect-timeout 12 https://google.com >/dev/null 2>>"$LOG" && return 0
+ fi
+
+ ping -c 1 -W 8 packages.termux.dev >> "$LOG" 2>&1 && return 0
+ ping -c 1 -W 8 google.com >> "$LOG" 2>&1 && return 0
+
+ return 1
+}
+
+wait_package_manager() {
+ local waited=0
+ while pgrep -x apt >/dev/null 2>&1 || \
+ pgrep -x apt-get >/dev/null 2>&1 || \
+ pgrep -x dpkg >/dev/null 2>&1; do
+ if [ "$waited" -ge 90 ]; then
+ die "$(t apt_stuck)"
+ fi
+ warn "$(t waiting_apt)"
+ sleep 3
+ waited=$((waited + 3))
+ done
+}
diff --git a/lib/common.sh b/lib/common.sh
new file mode 100644
index 0000000..9f43f48
--- /dev/null
+++ b/lib/common.sh
@@ -0,0 +1,315 @@
+#!/data/data/com.termux/files/usr/bin/bash
+# lib/common.sh — Cores, logging, spinner, helpers compartilhados
+# Sourced by script-termux.sh — NÃO executar diretamente.
+
+# =========================
+# Configuração global
+# =========================
+LOG="${HOME}/termux-linux-install.log"
+START_LOG="${HOME}/termux-linux-start.log"
+STATE_DIR="${HOME}/.termux-linux"
+SPINNER_PID=""
+TOTAL=11
+CURRENT=0
+
+DE_INPUT="1"
+DE_NAME=""
+DE_COMMAND=""
+DE_CORE_PACKAGES=()
+DE_EXTRA_PACKAGES=()
+GPU_DRIVER="software"
+GPU_ENABLED="false"
+GPU_INFO=""
+INSTALL_WINE="n"
+ARCH=""
+DEVICE_BRAND=""
+DEVICE_MODEL=""
+
+mkdir -p "$STATE_DIR"
+
+# =========================
+# Cores
+# =========================
+if [ -t 1 ]; then
+ RED=$'\e[31m'
+ GREEN=$'\e[32m'
+ YELLOW=$'\e[33m'
+ BLUE=$'\e[34m'
+ CYAN=$'\e[36m'
+ MAGENTA=$'\e[35m'
+ BOLD=$'\e[1m'
+ DIM=$'\e[2m'
+ RESET=$'\e[0m'
+else
+ RED=''
+ GREEN=''
+ YELLOW=''
+ BLUE=''
+ CYAN=''
+ MAGENTA=''
+ BOLD=''
+ DIM=''
+ RESET=''
+fi
+
+# =========================
+# Logging
+# =========================
+log_line() {
+ printf '[%s] %s\n' "$(date '+%Y-%m-%d %H:%M:%S')" "$*" >> "$LOG"
+}
+
+info() {
+ printf " %s->%s %s\n" "$BLUE" "$RESET" "$*"
+ log_line "INFO: $*"
+}
+
+ok() {
+ printf " %s[OK]%s %s\n" "$GREEN" "$RESET" "$*"
+ log_line "OK: $*"
+}
+
+warn() {
+ printf " %s[!]%s %s\n" "$YELLOW" "$RESET" "$*"
+ log_line "AVISO: $*"
+}
+
+show_log_tail() {
+ if [ -s "$LOG" ]; then
+ echo ""
+ echo " $(t last_log_lines)"
+ tail -n 25 "$LOG" | sed 's/^/ /'
+ fi
+}
+
+die() {
+ _stop_spinner
+ echo ""
+ printf " %s%s:%s %s\n" "$RED" "$(t error_prefix)" "$RESET" "$*" >&2
+ printf " %s\n" "$(t log_complete "$LOG")" >&2
+ show_log_tail >&2
+ exit 1
+}
+
+on_error() {
+ local line="$1"
+ local cmd="$2"
+ _stop_spinner
+ echo ""
+ printf " %s%s%s\n" "$RED" "$(t unexpected_error_line "$line" "$cmd")" "$RESET" >&2
+ printf " %s\n" "$(t log_complete "$LOG")" >&2
+ show_log_tail >&2
+ exit 1
+}
+
+# =========================
+# Spinner e Progresso
+# =========================
+_stop_spinner() {
+ if [ -n "${SPINNER_PID:-}" ]; then
+ kill "$SPINNER_PID" 2>/dev/null || true
+ wait "$SPINNER_PID" 2>/dev/null || true
+ printf "\r\033[K"
+ SPINNER_PID=""
+ fi
+ return 0
+}
+
+start_step() {
+ _stop_spinner
+ CURRENT=$((CURRENT + 1))
+ local msg="$1"
+ local pct=$((CURRENT * 100 / TOTAL))
+ local filled=$((pct * 24 / 100))
+ local bar_fill=""
+ local bar=""
+
+ if [ "$filled" -gt 0 ]; then
+ bar_fill=$(printf '%*s' "$filled" '' | tr ' ' '=')
+ fi
+
+ if [ "$filled" -lt 24 ]; then
+ bar=$(printf "%-24s" "${bar_fill}>")
+ else
+ bar="$bar_fill"
+ fi
+
+ echo ""
+ printf " %s[%02d/%02d]%s %s\n" "$BOLD" "$CURRENT" "$TOTAL" "$RESET" "$msg"
+ log_line "PASSO $CURRENT/$TOTAL: $msg"
+
+ (
+ i=0
+ chars='|/-\'
+ while true; do
+ printf "\r [%-24s] %3d%% %s" "$bar" "$pct" "${chars:$((i % 4)):1}"
+ i=$((i + 1))
+ sleep 0.2
+ done
+ ) &
+ SPINNER_PID=$!
+}
+
+end_step() {
+ _stop_spinner
+ ok "$(printf "$(t step_completed)" "$CURRENT" "$TOTAL")"
+}
+
+# =========================
+# Comandos e instalação
+# =========================
+run_cmd() {
+ local desc="$1"
+ shift
+ log_line "CMD: $*"
+ if ! "$@" >> "$LOG" 2>&1; then
+ die "$(printf "$(t failed_at)" "$desc")"
+ fi
+}
+
+install_with_retry() {
+ local pkg="$1"
+ local max_attempts="${2:-3}"
+ local attempt=1
+
+ while [ "$attempt" -le "$max_attempts" ]; do
+ if pkg install -y "$pkg" >> "$LOG" 2>&1; then
+ ok "$(printf "$(t installed)" "$pkg")"
+ return 0
+ fi
+ warn "$(printf "$(t attempt_failed)" "$attempt" "$max_attempts" "$pkg" "$attempt")"
+ sleep "$attempt"
+ attempt=$((attempt + 1))
+ done
+
+ return 1
+}
+
+install_required() {
+ local label="$1"
+ shift
+ local pkg_name=""
+ for pkg_name in "$@"; do
+ info "$(printf "$(t installing)" "$pkg_name")"
+ run_cmd "instalar $label: $pkg_name" pkg install -y "$pkg_name"
+ done
+}
+
+install_optional_packages() {
+ local pkg_name=""
+ for pkg_name in "$@"; do
+ info "$(printf "$(t trying_install_optional)" "$pkg_name")"
+ if pkg install -y "$pkg_name" >> "$LOG" 2>&1; then
+ ok "$(printf "$(t installed)" "$pkg_name")"
+ else
+ warn "$(printf "$(t optional_pkg_failed)" "$pkg_name")"
+ fi
+ done
+}
+
+install_any_required() {
+ local label="$1"
+ shift
+ local pkg_name=""
+
+ for pkg_name in "$@"; do
+ info "$(printf "$(t trying_install)" "$label" "$pkg_name")"
+ if pkg install -y "$pkg_name" >> "$LOG" 2>&1; then
+ ok "$(printf "$(t installed)" "$pkg_name")"
+ return 0
+ fi
+ done
+
+ die "$(printf "$(t no_option_available)" "$label" "$*")"
+}
+
+# =========================
+# Helpers
+# =========================
+command_exists() {
+ command -v "$1" >/dev/null 2>&1 || return 1
+}
+
+is_pkg_installed() {
+ dpkg -s "$1" > /dev/null 2>&1 || return 1
+}
+
+read_choice() {
+ local prompt="$1"
+ local default="$2"
+ local pattern="$3"
+ local value=""
+
+ while true; do
+ read -r -p "$prompt" value || value="$default"
+ value="${value:-$default}"
+ if [[ "$value" =~ $pattern ]]; then
+ printf '%s\n' "$value"
+ return 0
+ fi
+ echo " $(t invalid_option)"
+ done
+}
+
+read_yes_no() {
+ local prompt="$1"
+ local default="$2"
+ local value=""
+
+ while true; do
+ read -r -p "$prompt" value || value="$default"
+ value="${value:-$default}"
+ value="$(printf '%s' "$value" | tr '[:upper:]' '[:lower:]')"
+ case "$value" in
+ s|sim|y|yes) printf 'y\n'; return 0 ;;
+ n|nao|não|no) printf 'n\n'; return 0 ;;
+ *) echo " $(t answer_yes_no)" ;;
+ esac
+ done
+}
+
+pause_prompt() {
+ echo ""
+ read -r -p " $(t press_enter) " || true
+}
+
+# =========================
+# Config
+# =========================
+save_config() {
+ cat > "${STATE_DIR}/config.env" < "$PREFIX/etc/apt/apt.conf.d/99termux-noninteractive" <<'APTCONF'
+DPkg::Options {
+ "--force-confdef";
+ "--force-confold";
+};
+APTCONF
+}
diff --git a/lib/desktop.sh b/lib/desktop.sh
new file mode 100644
index 0000000..626d508
--- /dev/null
+++ b/lib/desktop.sh
@@ -0,0 +1,144 @@
+#!/data/data/com.termux/files/usr/bin/bash
+# lib/desktop.sh — Gerenciamento de ambientes desktop
+# Sourced by script-termux.sh — NAO executar diretamente.
+
+choose_desktop() {
+ echo ""
+ echo " -- $(t desktop_title) --"
+ echo " 1) $(t desktop_xfce4)"
+ echo " 2) $(t desktop_lxqt)"
+ echo " 3) $(t desktop_mate)"
+ echo " 4) $(t desktop_kde)"
+ echo ""
+
+ DE_INPUT="$(read_choice " $(t desktop_prompt)" '1' '^[1-4]$')"
+ _set_desktop_vars "$DE_INPUT"
+ ok "$(t desktop_chosen "$DE_NAME")"
+}
+
+_set_desktop_vars() {
+ case "$1" in
+ 1)
+ DE_NAME="XFCE4"
+ DE_COMMAND="startxfce4"
+ DE_CORE_PACKAGES=(xfce4 dbus pulseaudio)
+ DE_EXTRA_PACKAGES=(xfce4-terminal thunar mousepad pavucontrol shared-mime-info fontconfig)
+ ;;
+ 2)
+ DE_NAME="LXQt"
+ DE_COMMAND="startlxqt"
+ DE_CORE_PACKAGES=(lxqt-session openbox dbus pulseaudio)
+ DE_EXTRA_PACKAGES=(lxqt-panel pcmanfm-qt qterminal featherpad gtk3 pavucontrol shared-mime-info fontconfig)
+ ;;
+ 3)
+ DE_NAME="MATE"
+ DE_COMMAND="mate-session"
+ DE_CORE_PACKAGES=(mate-session-manager marco dbus pulseaudio)
+ DE_EXTRA_PACKAGES=(mate-panel mate-terminal fontconfig shared-mime-info)
+ ;;
+ 4)
+ DE_NAME="KDE Plasma"
+ DE_COMMAND="startplasma-x11"
+ DE_CORE_PACKAGES=(plasma-desktop dbus pulseaudio)
+ DE_EXTRA_PACKAGES=(konsole fontconfig shared-mime-info)
+ ;;
+ esac
+}
+
+install_desktop() {
+ local pkg_name=""
+
+ for pkg_name in "${DE_CORE_PACKAGES[@]}"; do
+ install_required "$(t step_installing_desktop "$DE_NAME"): $pkg_name" "$pkg_name"
+ done
+
+ install_optional_packages "${DE_EXTRA_PACKAGES[@]}"
+
+ if ! command_exists "$DE_COMMAND"; then
+ die "$(t desktop_command_not_found "$DE_COMMAND" "$DE_NAME")"
+ fi
+}
+
+remove_desktop() {
+ if [ -z "$DE_NAME" ]; then
+ warn "$(t desktop_none_installed)"
+ return 1
+ fi
+
+ local confirm=""
+ confirm="$(read_yes_no " $(t desktop_remove_confirm "$DE_NAME")" 'n')"
+ if [ "$confirm" != "y" ]; then
+ return 0
+ fi
+
+ info "$(t desktop_remove "$DE_NAME")"
+
+ case "$DE_NAME" in
+ XFCE4)
+ pkg remove -y xfce4 xfce4-terminal thunar mousepad >> "$LOG" 2>&1 || true
+ ;;
+ LXQt)
+ pkg remove -y lxqt-session openbox lxqt-panel pcmanfm-qt qterminal featherpad >> "$LOG" 2>&1 || true
+ ;;
+ MATE)
+ pkg remove -y mate-session-manager marco mate-panel mate-terminal >> "$LOG" 2>&1 || true
+ ;;
+ "KDE Plasma")
+ pkg remove -y plasma-desktop konsole >> "$LOG" 2>&1 || true
+ ;;
+ esac
+
+ pkg autoremove -y >> "$LOG" 2>&1 || true
+ ok "$(t desktop_removed "$DE_NAME")"
+ DE_NAME=""
+ DE_COMMAND=""
+ save_config
+}
+
+get_desktop_status() {
+ if [ -n "$DE_NAME" ] && command_exists "$DE_COMMAND"; then
+ printf '%s [OK]' "$DE_NAME"
+ elif [ -n "$DE_NAME" ]; then
+ printf '%s [!]' "$DE_NAME"
+ else
+ t status_not_installed
+ fi
+}
+
+desktop_menu() {
+ while true; do
+ echo ""
+ _header "$(t desktop_config_title)"
+ printf " | %-36s|\n" "$(t desktop_current "$(get_desktop_status)")"
+ _line
+ _item "1" "$(t desktop_change)"
+ _item "2" "$(t desktop_reinstall)"
+ _item "3" "$(t desktop_remove)"
+ _item "0" "$(t back)"
+ _footer
+ echo ""
+
+ local choice=""
+ read -r -p " $(t menu_prompt)" choice || choice="0"
+
+ case "$choice" in
+ 1)
+ choose_desktop
+ install_desktop
+ save_config
+ ;;
+ 2)
+ if [ -n "$DE_NAME" ]; then
+ install_desktop
+ else
+ warn "$(t desktop_none_installed)"
+ fi
+ ;;
+ 3) remove_desktop ;;
+ 0) return ;;
+ *) warn "$(t menu_invalid)" ;;
+ esac
+
+ pause_prompt
+ done
+}
diff --git a/lib/device.sh b/lib/device.sh
new file mode 100644
index 0000000..e7fb605
--- /dev/null
+++ b/lib/device.sh
@@ -0,0 +1,80 @@
+#!/data/data/com.termux/files/usr/bin/bash
+# lib/device.sh — Detecção de hardware e configuração de GPU
+# Sourced by script-termux.sh — NÃO executar diretamente.
+
+collect_device_info() {
+ ARCH="$(uname -m)"
+ DEVICE_BRAND="$(getprop ro.product.brand 2>/dev/null || echo 'Unknown')"
+ DEVICE_MODEL="$(getprop ro.product.model 2>/dev/null || echo 'Unknown')"
+ GPU_INFO="$(
+ {
+ getprop ro.hardware.egl
+ getprop ro.hardware.vulkan
+ getprop ro.board.platform
+ getprop ro.hardware
+ } 2>/dev/null | tr '[:upper:]' '[:lower:]'
+ )"
+
+ info "$(t architecture "$ARCH")"
+ info "$(t device_info "$DEVICE_BRAND" "$DEVICE_MODEL")"
+
+ if [ "$ARCH" != "aarch64" ]; then
+ warn "$(t wine_arm64_warning)"
+ fi
+}
+
+choose_gpu() {
+ echo ""
+ echo " -- $(t gpu_config_title) --"
+ echo " 1) $(t gpu_auto)"
+ echo " 2) $(t gpu_force_adreno)"
+ echo " 3) $(t gpu_disable)"
+ echo ""
+
+ local gpu_option=""
+ gpu_option="$(read_choice " $(t gpu_prompt)" '1' '^[1-3]$')"
+
+ case "$gpu_option" in
+ 1)
+ if printf '%s' "$GPU_INFO" | grep -Eq 'adreno|qcom|qualcomm|msm'; then
+ GPU_DRIVER="freedreno"
+ GPU_ENABLED="true"
+ ok "$(t gpu_adreno_detected)"
+ else
+ GPU_DRIVER="software"
+ GPU_ENABLED="false"
+ warn "$(t gpu_adreno_not_detected)"
+ fi
+ ;;
+ 2)
+ GPU_DRIVER="freedreno"
+ GPU_ENABLED="true"
+ warn "$(t gpu_forced_warning)"
+ ;;
+ 3)
+ GPU_DRIVER="software"
+ GPU_ENABLED="false"
+ ok "$(t gpu_disabled)"
+ ;;
+ esac
+}
+
+install_gpu_drivers() {
+ if [ "$GPU_ENABLED" = "true" ]; then
+ info "$(t gpu_base_install)"
+ if pkg install -y mesa-zink vulkan-loader-android >> "$LOG" 2>&1; then
+ ok "$(t gpu_base_installed)"
+ else
+ warn "$(t gpu_base_failed)"
+ GPU_ENABLED="false"
+ GPU_DRIVER="software"
+ return 0
+ fi
+
+ if [ "$GPU_DRIVER" = "freedreno" ]; then
+ install_optional_packages mesa-vulkan-icd-freedreno vulkan-tools
+ fi
+ else
+ ok "$(t gpu_software_mode)"
+ fi
+}
diff --git a/lib/i18n.sh b/lib/i18n.sh
new file mode 100644
index 0000000..be3bd44
--- /dev/null
+++ b/lib/i18n.sh
@@ -0,0 +1,79 @@
+#!/data/data/com.termux/files/usr/bin/bash
+# lib/i18n.sh — Sistema de internacionalização
+# Sourced by script-termux.sh — NÃO executar diretamente.
+
+CURRENT_LANG="${CURRENT_LANG:-pt}"
+declare -gA STRINGS
+
+# Traduz uma chave. Se houver argumentos extras, usa printf para interpolar.
+# Uso:
+# t "key" -> retorna string traduzida
+# t "key" "arg1" "arg2" -> printf com a string como template
+t() {
+ local key="$1"
+ shift
+ local template="${STRINGS[$key]:-$key}"
+ if [ $# -gt 0 ]; then
+ # shellcheck disable=SC2059
+ printf "$template" "$@"
+ else
+ printf '%s' "$template"
+ fi
+}
+
+# Carrega o arquivo de idioma
+load_language() {
+ local lang="${1:-$CURRENT_LANG}"
+ local lang_file="${SCRIPT_DIR}/lang/${lang}.sh"
+
+ if [ -f "$lang_file" ]; then
+ # shellcheck disable=SC1090
+ source "$lang_file"
+ CURRENT_LANG="$lang"
+ else
+ # Fallback para inglês
+ # shellcheck disable=SC1090
+ source "${SCRIPT_DIR}/lang/en.sh"
+ CURRENT_LANG="en"
+ fi
+}
+
+choose_language() {
+ echo ""
+ _header "Idioma / Language"
+ _item "1" "Portugues"
+ _item "2" "English"
+ _footer
+ echo ""
+
+ local choice=""
+ read -r -p " Opção / Option [1-2, padrão/default=1]: " choice || choice="1"
+ choice="${choice:-1}"
+
+ case "$choice" in
+ 1) load_language "pt" ;;
+ 2) load_language "en" ;;
+ *) load_language "pt" ;;
+ esac
+}
+
+# Detecta idioma do sistema (fallback automático)
+detect_language() {
+ # Primeiro checa se já tem config salva
+ if [ -f "${STATE_DIR:-}/config.env" ]; then
+ local saved_lang=""
+ saved_lang="$(grep '^CURRENT_LANG=' "${STATE_DIR}/config.env" 2>/dev/null | cut -d'"' -f2 || true)"
+ if [ -n "$saved_lang" ]; then
+ load_language "$saved_lang"
+ return 0
+ fi
+ fi
+
+ # Detecta pelo locale do sistema
+ local sys_lang="${LANG:-}"
+ case "$sys_lang" in
+ pt*) load_language "pt" ;;
+ en*) load_language "en" ;;
+ *) load_language "pt" ;; # Padrão: português
+ esac
+}
diff --git a/lib/menu.sh b/lib/menu.sh
new file mode 100644
index 0000000..595183e
--- /dev/null
+++ b/lib/menu.sh
@@ -0,0 +1,346 @@
+#!/data/data/com.termux/files/usr/bin/bash
+# lib/menu.sh — Sistema de menus interativo
+# Sourced by script-termux.sh — NAO executar diretamente.
+
+# =========================
+# Helpers de desenho de menu
+# =========================
+_line() {
+ echo " +--------------------------------------+"
+}
+
+_header() {
+ _line
+ printf " | %-36s|\n" "$1"
+ _line
+}
+
+_item() {
+ printf " | %s) %-33s|\n" "$1" "$2"
+}
+
+_footer() {
+ _line
+}
+
+# =========================
+# Banner com status
+# =========================
+banner() {
+ clear 2>/dev/null || true
+ echo ""
+ cat << 'ART'
+ | | |\ | | | \_/
+ |___ | | \| \__/ / \
+
+ __ __ __ __
+ /\ |\ | | \ |__) / \ | | \
+ /~~\ | \| |__/ | \ \__/ | |__/
+ART
+ echo ""
+ _header "$(t banner_title)"
+
+ # Mostrar status se tiver config carregada
+ if [ -n "$DE_NAME" ] || [ "$GPU_ENABLED" = "true" ]; then
+ echo ""
+ printf " %s%-10s%s %s\n" "$DIM" "$(t banner_status_desktop):" "$RESET" "$(get_desktop_status)"
+ if [ "$GPU_ENABLED" = "true" ]; then
+ printf " %s%-10s%s %s (%s)\n" "$DIM" "$(t banner_status_gpu):" "$RESET" "$GPU_DRIVER" "$(t status_enabled)"
+ else
+ printf " %s%-10s%s software (%s)\n" "$DIM" "$(t banner_status_gpu):" "$RESET" "$(t status_disabled)"
+ fi
+ printf " %s%-10s%s %s\n" "$DIM" "$(t banner_status_wine):" "$RESET" "$(get_wine_status)"
+ fi
+
+ echo ""
+}
+
+# =========================
+# Audio
+# =========================
+audio_menu() {
+ while true; do
+ echo ""
+ _header "$(t audio_title)"
+ _item "1" "$(t audio_install)"
+ _item "2" "$(t audio_restart)"
+ _item "3" "$(t audio_status)"
+ _item "0" "$(t back)"
+ _footer
+ echo ""
+
+ local choice=""
+ read -r -p " $(t menu_prompt)" choice || choice="0"
+
+ case "$choice" in
+ 1)
+ install_required "$(t audio_install)" pulseaudio
+ ok "$(t audio_installed)"
+ ;;
+ 2)
+ pulseaudio --kill >/dev/null 2>&1 || true
+ pulseaudio --start --exit-idle-time=-1 >> "$LOG" 2>&1 || true
+ ok "$(t audio_restarted)"
+ ;;
+ 3)
+ if pgrep -x pulseaudio >/dev/null 2>&1; then
+ ok "$(t audio_running)"
+ else
+ warn "$(t audio_not_running)"
+ fi
+ ;;
+ 0) return ;;
+ *) warn "$(t menu_invalid)" ;;
+ esac
+
+ pause_prompt
+ done
+}
+
+# =========================
+# GPU (submenu)
+# =========================
+gpu_menu() {
+ choose_gpu
+ install_gpu_drivers
+ save_config
+ pause_prompt
+}
+
+# =========================
+# Manutencao
+# =========================
+check_integrity() {
+ local missing=0
+ local cmds_to_check=(termux-x11 pulseaudio)
+
+ if [ -n "$DE_COMMAND" ]; then
+ cmds_to_check+=("$DE_COMMAND")
+ fi
+
+ for cmd in "${cmds_to_check[@]}"; do
+ if command_exists "$cmd"; then
+ ok "$cmd -- $(t maint_found)"
+ else
+ warn "$cmd -- $(t maint_not_found)"
+ missing=$((missing + 1))
+ fi
+ done
+
+ echo ""
+ if [ "$missing" -gt 0 ]; then
+ warn "$(t maint_components_missing "$missing")"
+ else
+ ok "$(t maint_all_ok)"
+ fi
+}
+
+maintenance_menu() {
+ while true; do
+ echo ""
+ _header "$(t maint_title)"
+ _item "1" "$(t maint_update)"
+ _item "2" "$(t maint_check_integrity)"
+ _item "3" "$(t maint_view_install_log)"
+ _item "4" "$(t maint_view_start_log)"
+ _item "5" "$(t maint_clean_cache)"
+ _item "6" "$(t maint_recreate_scripts)"
+ _item "7" "$(t maint_diagnostics)"
+ _item "0" "$(t back)"
+ _footer
+ echo ""
+
+ local choice=""
+ read -r -p " $(t menu_prompt)" choice || choice="0"
+
+ case "$choice" in
+ 1)
+ info "$(t maint_updating)"
+ run_cmd "pkg update" pkg update -y
+ run_cmd "pkg upgrade" pkg upgrade -y
+ ok "$(t maint_updated)"
+ ;;
+ 2) check_integrity ;;
+ 3)
+ echo ""
+ if [ -s "$LOG" ]; then
+ tail -n 50 "$LOG" | sed 's/^/ /'
+ else
+ warn "Log vazio."
+ fi
+ ;;
+ 4)
+ echo ""
+ if [ -s "$START_LOG" ]; then
+ tail -n 50 "$START_LOG" | sed 's/^/ /'
+ else
+ warn "Log vazio."
+ fi
+ ;;
+ 5)
+ info "$(t maint_clean_cache)..."
+ pkg clean >> "$LOG" 2>&1 || true
+ apt autoclean >> "$LOG" 2>&1 || true
+ ok "$(t maint_cache_cleaned)"
+ ;;
+ 6)
+ if [ -n "$DE_NAME" ]; then
+ write_all_scripts
+ else
+ warn "$(t desktop_none_installed)"
+ fi
+ ;;
+ 7)
+ if [ -x "${HOME}/linux-info.sh" ]; then
+ bash "${HOME}/linux-info.sh"
+ else
+ check_integrity
+ fi
+ ;;
+ 0) return ;;
+ *) warn "$(t menu_invalid)" ;;
+ esac
+
+ pause_prompt
+ done
+}
+
+# =========================
+# Instalacao Completa (fluxo linear original)
+# =========================
+full_install() {
+ banner
+
+ info "$(t checking_internet)"
+ check_internet || die "$(t no_internet)"
+
+ collect_device_info
+ choose_gpu
+ choose_desktop
+
+ echo ""
+ local wine_answer=""
+ wine_answer="$(read_yes_no " $(t wine_install_prompt)" 'n')"
+ if [ "$wine_answer" = "y" ]; then
+ INSTALL_WINE="y"
+ fi
+
+ : > "$LOG"
+
+ start_step "$(t step_preparing)"
+ prepare_environment
+ wait_package_manager
+ run_cmd "corrigir dpkg pendente" dpkg --configure -a
+ end_step
+
+ start_step "$(t step_updating)"
+ run_cmd "pkg update" pkg update -y
+ run_cmd "pkg upgrade" pkg upgrade -y
+ end_step
+
+ start_step "$(t step_adding_repos)"
+ install_required "repositorios" x11-repo tur-repo
+ run_cmd "atualizar lista apos repositorios" pkg update -y
+ end_step
+
+ start_step "$(t step_graphics_server)"
+ install_any_required "Termux-X11" termux-x11 termux-x11-nightly
+ install_required "ferramentas X11" xorg-xrandr xorg-xhost xorg-xsetroot
+ end_step
+
+ start_step "$(t step_installing_desktop "$DE_NAME")"
+ install_desktop
+ end_step
+
+ start_step "$(t step_configuring_gpu)"
+ install_gpu_drivers
+ end_step
+
+ start_step "$(t step_installing_audio)"
+ install_required "audio" pulseaudio
+ end_step
+
+ start_step "$(t step_installing_apps)"
+ install_basic_apps
+ end_step
+
+ start_step "$(t step_configuring_wine)"
+ install_wine_if_requested
+ end_step
+
+ start_step "$(t step_creating_scripts)"
+ write_start_script
+ write_stop_script
+ write_info_script
+ save_config
+ end_step
+
+ start_step "$(t step_creating_shortcuts)"
+ create_desktop_shortcuts
+ end_step
+
+ _stop_spinner
+ echo ""
+ if command_exists neofetch; then
+ neofetch || true
+ fi
+
+ echo ""
+ _header "$(t install_complete)"
+ echo ""
+ echo " $(t install_desktop_label) : $DE_NAME"
+ echo " $(t install_gpu_label) : $GPU_DRIVER / enabled=$GPU_ENABLED"
+ echo ""
+ echo " $(t install_start_cmd) : ~/start-linux.sh"
+ echo " $(t install_stop_cmd) : ~/stop-linux.sh"
+ echo " $(t install_info_cmd) : ~/linux-info.sh"
+ echo " $(t install_log_label) : $LOG"
+ echo ""
+ echo " $(t install_open_x11)"
+ echo ""
+}
+
+# =========================
+# Menu principal
+# =========================
+main_menu() {
+ while true; do
+ banner
+
+ _header "$(t menu_title)"
+ _item "1" "$(t menu_full_install)"
+ _item "2" "$(t menu_apps)"
+ _item "3" "$(t menu_desktop)"
+ _item "4" "$(t menu_gpu)"
+ _item "5" "$(t menu_audio)"
+ _item "6" "$(t menu_wine)"
+ _item "7" "$(t menu_themes)"
+ _item "8" "$(t menu_maintenance)"
+ _item "9" "$(t menu_backup)"
+ _item "0" "$(t menu_exit)"
+ _footer
+ echo ""
+
+ local choice=""
+ read -r -p " $(t menu_prompt)" choice || choice="0"
+
+ case "$choice" in
+ 1) full_install ; pause_prompt ;;
+ 2) apps_menu ;;
+ 3) desktop_menu ;;
+ 4) gpu_menu ;;
+ 5) audio_menu ;;
+ 6) wine_menu ;;
+ 7) themes_menu ;;
+ 8) maintenance_menu ;;
+ 9) backup_menu ;;
+ 0)
+ echo ""
+ echo " $(t menu_goodbye)"
+ echo ""
+ exit 0
+ ;;
+ *) warn "$(t menu_invalid)" ; sleep 1 ;;
+ esac
+ done
+}
diff --git a/lib/scripts.sh b/lib/scripts.sh
new file mode 100644
index 0000000..8b14264
--- /dev/null
+++ b/lib/scripts.sh
@@ -0,0 +1,159 @@
+#!/data/data/com.termux/files/usr/bin/bash
+# lib/scripts.sh — Geração de scripts auxiliares (start, stop, info)
+# Sourced by script-termux.sh — NÃO executar diretamente.
+
+write_start_script() {
+ cat > "${HOME}/start-linux.sh" < "\$LOG"
+
+export LANG=C.UTF-8
+export LC_ALL=C.UTF-8
+export TMPDIR="\${TMPDIR:-/data/data/com.termux/files/usr/tmp}"
+mkdir -p "\$TMPDIR"
+
+export XDG_RUNTIME_DIR="\$TMPDIR"
+export DISPLAY=:0
+export XDG_SESSION_TYPE=x11
+export QT_X11_NO_MITSHM=1
+export NO_AT_BRIDGE=1
+export PULSE_SERVER=127.0.0.1
+EOF_START
+
+ if [ "$GPU_ENABLED" = "true" ]; then
+ cat >> "${HOME}/start-linux.sh" <<'EOF_GPU'
+export GALLIUM_DRIVER=zink
+export MESA_LOADER_DRIVER_OVERRIDE=zink
+export MESA_NO_ERROR=1
+EOF_GPU
+ else
+ cat >> "${HOME}/start-linux.sh" <<'EOF_GPU'
+export LIBGL_ALWAYS_SOFTWARE=1
+EOF_GPU
+ fi
+
+ cat >> "${HOME}/start-linux.sh" </dev/null || true
+ pkill -f "termux-x11.*:0" 2>/dev/null || true
+ pulseaudio --kill >/dev/null 2>&1 || true
+}
+
+start_audio() {
+ pulseaudio --start --exit-idle-time=-1 >> "\$LOG" 2>&1 || true
+ pactl load-module module-native-protocol-tcp auth-ip-acl=127.0.0.1 auth-anonymous=1 >> "\$LOG" 2>&1 || true
+}
+
+start_x11() {
+ am start --user 0 -n com.termux.x11/com.termux.x11.MainActivity >> "\$LOG" 2>&1 || true
+ termux-x11 :0 >> "\$LOG" 2>&1 &
+ sleep 3
+}
+
+echo "Iniciando Termux Linux/X11..."
+stop_old_sessions
+sleep 1
+start_audio
+start_x11
+
+start_desktop() {
+ cd "\$HOME"
+
+ if command -v dbus-launch >/dev/null 2>&1; then
+ exec dbus-launch --exit-with-session ${DE_COMMAND}
+ fi
+
+ echo "Aviso: dbus-launch não encontrado. Iniciando ${DE_NAME} sem dbus-launch." >> "\$LOG"
+ exec ${DE_COMMAND}
+}
+
+start_desktop
+EOF_START2
+
+ chmod +x "${HOME}/start-linux.sh"
+}
+
+write_stop_script() {
+ cat > "${HOME}/stop-linux.sh" <<'EOF_STOP'
+#!/data/data/com.termux/files/usr/bin/bash
+
+pkill -f "startxfce4|startlxqt|mate-session|startplasma-x11|xfce4-session|lxqt-session" 2>/dev/null || true
+pkill -f "termux-x11.*:0" 2>/dev/null || true
+pulseaudio --kill >/dev/null 2>&1 || true
+
+echo "Desktop finalizado."
+EOF_STOP
+
+ chmod +x "${HOME}/stop-linux.sh"
+}
+
+write_info_script() {
+ cat > "${HOME}/linux-info.sh" <<'EOF_INFO'
+#!/data/data/com.termux/files/usr/bin/bash
+
+echo "===== Termux Linux/X11 - Diagnóstico ====="
+echo "Data: $(date)"
+echo "Arquitetura: $(uname -m)"
+echo "PREFIX: ${PREFIX:-desconhecido}"
+echo "DISPLAY: ${DISPLAY:-não definido}"
+echo ""
+echo "Comandos encontrados:"
+for cmd in termux-x11 dbus-launch startxfce4 startlxqt mate-session startplasma-x11 pulseaudio; do
+ if command -v "$cmd" >/dev/null 2>&1; then
+ echo " [OK] $cmd -> $(command -v "$cmd")"
+ else
+ echo " - $cmd não encontrado"
+ fi
+done
+
+echo ""
+echo "Últimas linhas do log de instalação:"
+tail -n 30 "$HOME/termux-linux-install.log" 2>/dev/null || true
+
+echo ""
+echo "Últimas linhas do log de inicialização:"
+tail -n 30 "$HOME/termux-linux-start.log" 2>/dev/null || true
+EOF_INFO
+
+ chmod +x "${HOME}/linux-info.sh"
+}
+
+create_desktop_shortcuts() {
+ mkdir -p "${HOME}/Desktop"
+
+ if command_exists firefox; then
+ cat > "${HOME}/Desktop/Firefox.desktop" <<'EOF_FIREFOX'
+[Desktop Entry]
+Name=Firefox
+Exec=firefox
+Type=Application
+Categories=Network;WebBrowser;
+Terminal=false
+EOF_FIREFOX
+ fi
+
+ if command_exists code-oss; then
+ cat > "${HOME}/Desktop/CodeOSS.desktop" <<'EOF_CODE'
+[Desktop Entry]
+Name=Code OSS
+Exec=code-oss --no-sandbox
+Type=Application
+Categories=Development;
+Terminal=false
+EOF_CODE
+ fi
+
+ chmod +x "${HOME}/Desktop"/*.desktop 2>/dev/null || true
+}
+
+write_all_scripts() {
+ write_start_script
+ write_stop_script
+ write_info_script
+ create_desktop_shortcuts
+ ok "$(t scripts_created)"
+}
diff --git a/lib/themes.sh b/lib/themes.sh
new file mode 100644
index 0000000..9ab8a73
--- /dev/null
+++ b/lib/themes.sh
@@ -0,0 +1,133 @@
+#!/data/data/com.termux/files/usr/bin/bash
+# lib/themes.sh — Temas e personalização
+# Sourced by script-termux.sh — NÃO executar diretamente.
+
+install_dark_theme() {
+ echo ""
+ echo " -- $(t themes_dark) --"
+ echo " 1) $(t themes_arc_dark)"
+ echo " 2) $(t themes_gruvbox)"
+ echo ""
+
+ local choice=""
+ choice="$(read_choice " $(t themes_select_theme)" '1' '^[1-2]$')"
+
+ case "$choice" in
+ 1)
+ install_optional_packages arc-theme
+ # Aplicar tema no XFCE4 se disponível
+ if command_exists xfconf-query; then
+ xfconf-query -c xsettings -p /Net/ThemeName -s "Arc-Dark" 2>/dev/null || true
+ xfconf-query -c xfwm4 -p /general/theme -s "Arc-Dark" 2>/dev/null || true
+ fi
+ ok "$(t themes_installed "Arc Dark")"
+ ;;
+ 2)
+ install_optional_packages gruvbox-dark-gtk
+ if command_exists xfconf-query; then
+ xfconf-query -c xsettings -p /Net/ThemeName -s "Gruvbox-Dark" 2>/dev/null || true
+ fi
+ ok "$(t themes_installed "Gruvbox Dark")"
+ ;;
+ esac
+}
+
+install_icon_pack() {
+ echo ""
+ echo " -- $(t themes_icons) --"
+ echo " 1) $(t themes_papirus)"
+ echo " 2) $(t themes_adwaita)"
+ echo ""
+
+ local choice=""
+ choice="$(read_choice " $(t themes_select_icons)" '1' '^[1-2]$')"
+
+ case "$choice" in
+ 1)
+ install_optional_packages papirus-icon-theme
+ if command_exists xfconf-query; then
+ xfconf-query -c xsettings -p /Net/IconThemeName -s "Papirus-Dark" 2>/dev/null || true
+ fi
+ ok "$(t themes_icons_installed "Papirus")"
+ ;;
+ 2)
+ install_optional_packages adwaita-icon-theme
+ if command_exists xfconf-query; then
+ xfconf-query -c xsettings -p /Net/IconThemeName -s "Adwaita" 2>/dev/null || true
+ fi
+ ok "$(t themes_icons_installed "Adwaita")"
+ ;;
+ esac
+}
+
+install_fonts() {
+ info "$(t themes_fonts)..."
+ install_optional_packages \
+ fontconfig \
+ font-dejavu \
+ font-noto \
+ font-noto-emoji
+
+ # Rebuild font cache
+ if command_exists fc-cache; then
+ fc-cache -fv >> "$LOG" 2>&1 || true
+ fi
+
+ ok "$(t themes_fonts_installed)"
+}
+
+set_wallpaper() {
+ local wallpaper_path=""
+ read -r -p " $(t themes_wallpaper_path)" wallpaper_path || return
+
+ if [ -z "$wallpaper_path" ]; then
+ return
+ fi
+
+ if [ ! -f "$wallpaper_path" ]; then
+ warn "$(t themes_wallpaper_not_found)"
+ return 1
+ fi
+
+ # Copia para pasta local
+ mkdir -p "${HOME}/.local/share/wallpapers"
+ cp "$wallpaper_path" "${HOME}/.local/share/wallpapers/current-wallpaper" 2>/dev/null || true
+
+ # Tenta aplicar no XFCE4
+ if command_exists xfconf-query; then
+ local monitor=""
+ for monitor in $(xfconf-query -c xfce4-desktop -l 2>/dev/null | grep "last-image$"); do
+ xfconf-query -c xfce4-desktop -p "$monitor" -s "$wallpaper_path" 2>/dev/null || true
+ done
+ fi
+
+ ok "$(t themes_wallpaper_set)"
+}
+
+themes_menu() {
+ while true; do
+ echo ""
+ _header "$(t themes_title)"
+ _item "1" "$(t themes_dark)"
+ _item "2" "$(t themes_icons)"
+ _item "3" "$(t themes_wallpaper)"
+ _item "4" "$(t themes_fonts)"
+ _item "0" "$(t back)"
+ _footer
+ echo ""
+
+ local choice=""
+ read -r -p " $(t menu_prompt)" choice || choice="0"
+
+ case "$choice" in
+ 1) install_dark_theme ;;
+ 2) install_icon_pack ;;
+ 3) set_wallpaper ;;
+ 4) install_fonts ;;
+ 0) return ;;
+ *) warn "$(t menu_invalid)" ;;
+ esac
+
+ pause_prompt
+ done
+}
diff --git a/lib/wine.sh b/lib/wine.sh
new file mode 100644
index 0000000..7c568fc
--- /dev/null
+++ b/lib/wine.sh
@@ -0,0 +1,86 @@
+#!/data/data/com.termux/files/usr/bin/bash
+# lib/wine.sh — Gerenciamento de Wine/Hangover
+# Sourced by script-termux.sh — NÃO executar diretamente.
+
+install_wine() {
+ if [ "${ARCH:-}" != "aarch64" ]; then
+ warn "$(t wine_not_arm64)"
+ fi
+
+ if is_pkg_installed wine-stable; then
+ run_cmd "remover wine-stable antigo" pkg remove -y wine-stable
+ fi
+
+ install_optional_packages hangover-wine hangover-wowbox64
+
+ if [ -x "$PREFIX/opt/hangover-wine/bin/wine" ]; then
+ ln -sf "$PREFIX/opt/hangover-wine/bin/wine" "$PREFIX/bin/wine"
+ ok "$(t wine_shortcut_created)"
+ else
+ warn "$(t wine_not_complete)"
+ fi
+
+ INSTALL_WINE="y"
+ save_config
+}
+
+remove_wine() {
+ local confirm=""
+ confirm="$(read_yes_no " $(t wine_remove_confirm)" 'n')"
+ if [ "$confirm" != "y" ]; then
+ return 0
+ fi
+
+ info "$(t wine_remove)..."
+ pkg remove -y hangover-wine hangover-wowbox64 >> "$LOG" 2>&1 || true
+ rm -f "$PREFIX/bin/wine" 2>/dev/null || true
+ pkg autoremove -y >> "$LOG" 2>&1 || true
+ ok "$(t wine_removed)"
+
+ INSTALL_WINE="n"
+ save_config
+}
+
+get_wine_status() {
+ if command_exists wine; then
+ t status_installed
+ else
+ t status_not_installed
+ fi
+}
+
+wine_menu() {
+ while true; do
+ echo ""
+ _header "$(t wine_config_title)"
+ printf " | Wine: %-30s|\n" "$(get_wine_status)"
+ _line
+ _item "1" "$(t wine_install)"
+ _item "2" "$(t wine_remove)"
+ _item "0" "$(t back)"
+ _footer
+ echo ""
+
+ local choice=""
+ read -r -p " $(t menu_prompt)" choice || choice="0"
+
+ case "$choice" in
+ 1) install_wine ;;
+ 2) remove_wine ;;
+ 0) return ;;
+ *) warn "$(t menu_invalid)" ;;
+ esac
+
+ pause_prompt
+ done
+}
+
+# Usado na instalação completa
+install_wine_if_requested() {
+ if [ "$INSTALL_WINE" != "y" ]; then
+ ok "$(t wine_skipped)"
+ return 0
+ fi
+
+ install_wine
+}
diff --git a/script-termux.sh b/script-termux.sh
index 01b1a00..c4d6d64 100644
--- a/script-termux.sh
+++ b/script-termux.sh
@@ -1,149 +1,171 @@
#!/data/data/com.termux/files/usr/bin/bash
-
-# Script Linux simplificado para Termux
-
-# ============== CONFIGURAÇÃO BÁSICA ==============
-DE_CHOICE="1"
-DE_NAME="XFCE4"
-GPU_DRIVER=""
-
-# ============== FUNÇÕES SIMPLIFICADAS ==============
-print_step() {
- echo "[$1/$2] $3"
-}
-
-install_pkg() {
- echo " -> Instalando $1..."
- apt-get install -y -q $1 > /dev/null 2>&1
+# Ponto de entrada modular para Configuração do Termux Linux/X11
+# Entrypoint for Termux Linux/X11 Configuration
+
+set -Eeuo pipefail
+IFS=$'\n\t'
+
+# Define o diretório do script
+SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
+export SCRIPT_DIR
+
+# 1. Carrega o core (common e i18n)
+# shellcheck disable=SC1091
+source "${SCRIPT_DIR}/lib/common.sh"
+# shellcheck disable=SC1091
+source "${SCRIPT_DIR}/lib/i18n.sh"
+
+# 2. Carrega todos os outros módulos de biblioteca
+# shellcheck disable=SC1091
+source "${SCRIPT_DIR}/lib/checks.sh"
+# shellcheck disable=SC1091
+source "${SCRIPT_DIR}/lib/device.sh"
+# shellcheck disable=SC1091
+source "${SCRIPT_DIR}/lib/desktop.sh"
+# shellcheck disable=SC1091
+source "${SCRIPT_DIR}/lib/apps.sh"
+# shellcheck disable=SC1091
+source "${SCRIPT_DIR}/lib/wine.sh"
+# shellcheck disable=SC1091
+source "${SCRIPT_DIR}/lib/themes.sh"
+# shellcheck disable=SC1091
+source "${SCRIPT_DIR}/lib/scripts.sh"
+# shellcheck disable=SC1091
+source "${SCRIPT_DIR}/lib/backup.sh"
+# shellcheck disable=SC1091
+source "${SCRIPT_DIR}/lib/menu.sh"
+
+# Armadilha de erro configurada no common.sh
+trap 'on_error "$LINENO" "$BASH_COMMAND"' ERR
+trap '_stop_spinner' EXIT
+
+# Processamento de flags da CLI
+show_help() {
+ echo "Uso / Usage: ./script-termux.sh [opções / options]"
+ echo ""
+ echo "Opções / Options:"
+ echo " --help, -h Mostra esta mensagem de ajuda / Show this help message"
+ echo " --install Inicia a instalação completa automática / Start automated full installation"
+ echo " --desktop [de] Instala um desktop específico (xfce4, lxqt, mate, kde) / Install specific desktop"
+ echo " --app [nome] Instala um aplicativo específico do catálogo / Install a specific app from catalog"
+ echo " --lang [pt|en] Força o idioma do script / Force script language"
+ echo ""
+ exit 0
}
-# ============== DETECÇÃO DO DISPOSITIVO ==============
-echo "=== Configurando Termux Linux ==="
-echo ""
-
-DEVICE_BRAND=$(getprop ro.product.brand 2>/dev/null || echo "Unknown")
-GPU_VENDOR=$(getprop ro.hardware.egl 2>/dev/null || echo "")
-
-echo "Dispositivo: $DEVICE_BRAND"
-
-# ============== SELEÇÃO DO DESKTOP ==============
-echo ""
-echo "Escolha o Desktop:"
-echo "1) XFCE4 (recomendado)"
-echo "2) LXQt (leve)"
-echo "3) MATE (médio)"
-echo "4) KDE (pesado)"
-read -p "Opção [1-4, padrão=1]: " DE_INPUT
-DE_INPUT=${DE_INPUT:-1}
-
-case $DE_INPUT in
- 1) DE_NAME="XFCE4";;
- 2) DE_NAME="LXQt";;
- 3) DE_NAME="MATE";;
- 4) DE_NAME="KDE Plasma";;
-esac
-echo "Selecionado: $DE_NAME"
-
-# ============== INSTALAÇÃO (11 PASSOS) ==============
-TOTAL=11
-CURRENT=0
-
-# Passo 1
-CURRENT=$((CURRENT+1)); print_step $CURRENT $TOTAL "Atualizando sistema"
-apt-get update -y -q > /dev/null 2>&1
-apt-get upgrade -y -q > /dev/null 2>&1
-
-# Passo 2
-CURRENT=$((CURRENT+1)); print_step $CURRENT $TOTAL "Adicionando repositórios"
-apt-get install -y -q x11-repo tur-repo > /dev/null 2>&1
-
-# Passo 3
-CURRENT=$((CURRENT+1)); print_step $CURRENT $TOTAL "Instalando servidor gráfico"
-apt-get install -y -q termux-x11-nightly xorg-xrandr > /dev/null 2>&1
-
-# Passo 4
-CURRENT=$((CURRENT+1)); print_step $CURRENT $TOTAL "Instalando $DE_NAME"
-case $DE_INPUT in
- 1) install_pkg "xfce4 xfce4-terminal xfce4-whiskermenu-plugin plank-reloaded thunar mousepad";;
- 2) install_pkg "lxqt qterminal pcmanfm-qt featherpad";;
- 3) install_pkg "mate mate-tweak plank-reloaded mate-terminal";;
- 4) install_pkg "plasma-desktop konsole dolphin";;
-esac
-
-# Passo 5
-CURRENT=$((CURRENT+1)); print_step $CURRENT $TOTAL "Instalando drivers GPU"
-apt-get install -y -q mesa-zink vulkan-loader-android > /dev/null 2>&1
-[ "$GPU_DRIVER" == "freedreno" ] && apt-get install -y -q mesa-vulkan-icd-freedreno > /dev/null 2>&1
-
-# Passo 6
-CURRENT=$((CURRENT+1)); print_step $CURRENT $TOTAL "Instalando áudio"
-apt-get install -y -q pulseaudio > /dev/null 2>&1
-
-# Passo 7
-CURRENT=$((CURRENT+1)); print_step $CURRENT $TOTAL "Instalando apps"
-apt-get install -y -q firefox vlc git wget curl > /dev/null 2>&1
-
-# Passo 8
-CURRENT=$((CURRENT+1)); print_step $CURRENT $TOTAL "Instalando Python"
-apt-get install -y -q python > /dev/null 2>&1
-pip install flask > /dev/null 2>&1
-
-# Passo 9
-CURRENT=$((CURRENT+1)); print_step $CURRENT $TOTAL "Instalando Wine"
-apt-get remove -y wine-stable > /dev/null 2>&1
-apt-get install -y -q hangover-wine hangover-wowbox64 > /dev/null 2>&1
-ln -sf /data/data/com.termux/files/usr/opt/hangover-wine/bin/wine /data/data/com.termux/files/usr/bin/wine 2>/dev/null
-
-# Passo 10
-CURRENT=$((CURRENT+1)); print_step $CURRENT $TOTAL "Criando scripts"
-cat > ~/start-linux.sh << 'EOF'
-#!/data/data/com.termux/files/usr/bin/bash
-pkill -9 -f "termux.x11" 2>/dev/null
-pulseaudio --kill 2>/dev/null
-sleep 1
-pulseaudio --start --exit-idle-time=-1
-export PULSE_SERVER=127.0.0.1
-termux-x11 :0 -ac &
-sleep 2
-export DISPLAY=:0
-EOF
-
-if [ "$DE_INPUT" == "1" ]; then
- echo "exec startxfce4" >> ~/start-linux.sh
-elif [ "$DE_INPUT" == "2" ]; then
- echo "exec startlxqt" >> ~/start-linux.sh
-elif [ "$DE_INPUT" == "3" ]; then
- echo "exec mate-session" >> ~/start-linux.sh
+# Define variáveis para as ações CLI
+ACTION="menu"
+DESKTOP_ARG=""
+APP_ARG=""
+FORCE_LANG=""
+
+# Processamento de argumentos
+while (( "$#" )); do
+ case "$1" in
+ -h|--help)
+ show_help
+ ;;
+ --install)
+ ACTION="install"
+ shift
+ ;;
+ --desktop)
+ ACTION="desktop"
+ if [ -n "${2:-}" ]; then
+ DESKTOP_ARG="$2"
+ shift 2
+ else
+ echo "Erro: Faltou especificar o desktop (xfce4, lxqt, mate, kde)." >&2
+ exit 1
+ fi
+ ;;
+ --app)
+ ACTION="app"
+ if [ -n "${2:-}" ]; then
+ APP_ARG="$2"
+ shift 2
+ else
+ echo "Erro: Faltou especificar o nome do aplicativo." >&2
+ exit 1
+ fi
+ ;;
+ --lang)
+ if [ -n "${2:-}" ]; then
+ FORCE_LANG="$2"
+ shift 2
+ else
+ echo "Erro: Faltou especificar o idioma (pt, en)." >&2
+ exit 1
+ fi
+ ;;
+ *)
+ echo "Erro: Flag não suportada / Unsupported flag: $1" >&2
+ show_help
+ ;;
+ esac
+done
+
+# Inicialização e detecção de idioma
+load_config || true
+
+if [ -n "$FORCE_LANG" ]; then
+ case "$FORCE_LANG" in
+ pt|en) load_language "$FORCE_LANG" ;;
+ *) echo "Idioma inválido. Opções: pt, en. / Invalid language. Options: pt, en." >&2; exit 1 ;;
+ esac
else
- echo "exec startplasma-x11" >> ~/start-linux.sh
+ detect_language
fi
-chmod +x ~/start-linux.sh
-
-cat > ~/stop-linux.sh << 'EOF'
-#!/data/data/com.termux/files/usr/bin/bash
-pkill -9 -f "termux.x11" 2>/dev/null
-pkill -9 pulseaudio 2>/dev/null
-echo "Desktop finalizado"
-EOF
-chmod +x ~/stop-linux.sh
-
-# Passo 11
-CURRENT=$((CURRENT+1)); print_step $CURRENT $TOTAL "Criando atalhos"
-mkdir -p ~/Desktop
-cat > ~/Desktop/Firefox.desktop << 'EOF'
-[Desktop Entry]
-Name=Firefox
-Exec=firefox
-Type=Application
-EOF
-chmod +x ~/Desktop/*.desktop 2>/dev/null
-
-# ============== FINALIZAÇÃO ==============
-echo ""
-echo "=== INSTALAÇÃO CONCLUÍDA ==="
-echo ""
-echo "Para iniciar o desktop: ./start-linux.sh"
-echo "Para parar: ./stop-linux.sh"
-echo "Abra o app Termux-X11 para ver a interface"
-echo ""
+# Agora executa a verificação obrigatória de ambiente
+require_termux
+
+# Executa a ação selecionada
+case "$ACTION" in
+ install)
+ full_install
+ ;;
+ desktop)
+ case "$(echo "$DESKTOP_ARG" | tr '[:upper:]' '[:lower:]')" in
+ xfce4) _set_desktop_vars 1 ;;
+ lxqt) _set_desktop_vars 2 ;;
+ mate) _set_desktop_vars 3 ;;
+ kde) _set_desktop_vars 4 ;;
+ *) die "Desktop inválido. Opções: xfce4, lxqt, mate, kde." ;;
+ esac
+ install_desktop
+ save_config
+ ;;
+ app)
+ # Procura o app no catálogo apps.conf
+ app_found=false
+ app_pkg=""
+ app_name=""
+ while IFS='|' read -r _cat name pkg; do
+ clean_name="$(echo "$name" | tr '[:upper:]' '[:lower:]')"
+ clean_pkg="$(echo "$pkg" | tr '[:upper:]' '[:lower:]')"
+ target_arg="$(echo "$APP_ARG" | tr '[:upper:]' '[:lower:]')"
+ if [[ "$clean_name" == *"$target_arg"* ]] || [[ "$clean_pkg" == *"$target_arg"* ]]; then
+ app_pkg="$pkg"
+ app_name="$name"
+ app_found=true
+ break
+ fi
+ done < "${SCRIPT_DIR}/apps.conf"
+
+ if [ "$app_found" = true ]; then
+ info "$(t installing "$app_name")"
+ # shellcheck disable=SC2086
+ install_with_retry $app_pkg || die "$(t optional_pkg_failed "$app_name")"
+ else
+ die "Aplicativo '$APP_ARG' não encontrado no catálogo apps.conf."
+ fi
+ ;;
+ menu)
+ # Se for a primeira execução (sem desktop configurado no config.env), perguntar o idioma primeiro.
+ if [ -z "${DE_NAME:-}" ] && [ ! -f "${STATE_DIR}/config.env" ]; then
+ choose_language
+ fi
+ main_menu
+ ;;
+esac