feat: pré-visualização completa, tema, nova identidade e correções (0.2.0)
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 / 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
- Preview de imagem, vídeo/MP4, áudio, PDF (pdf.js), texto, Office/ODF, ZIP e hex, lido sob demanda com Range; tela cheia com navegação por teclado. - Seletor de tema Auto/Claro/Escuro persistido (vale também como administrador). - Identidade verde-azulada com logo de pixels que formam um lobo. - Corrige reinício como administrador no AppImage (usa $APPIMAGE) e mostra o motivo. - Corrige barra inferior piscando (render idempotente, barra criada uma vez). - Corrige FAT32 em mídias pequenas não reconhecido. Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
This commit is contained in:
1 parent
510f1bc48e
commit
c5c94a9956
32 files changed
+1666
-227
No files matched your search
@@ -0,0 +1,118 @@
|
||||
//! Preferências do usuário (tema etc.), compartilhadas entre o app normal e o
|
||||
//! reiniciado como administrador.
|
||||
|
||||
use crate::error::Result;
|
||||
use serde::{Deserialize, Serialize};
|
||||
use std::path::PathBuf;
|
||||
|
||||
#[derive(Debug, Clone, Serialize, Deserialize)]
|
||||
pub struct Settings {
|
||||
/// "auto", "light" ou "dark".
|
||||
pub theme: String,
|
||||
}
|
||||
|
||||
impl Default for Settings {
|
||||
fn default() -> Self {
|
||||
Self {
|
||||
theme: "auto".into(),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// Pasta de configuração do usuário *real*, mesmo quando rodando como root
|
||||
/// via sudo/pkexec (para o tema não "mudar" ao elevar privilégios).
|
||||
pub fn config_dir() -> PathBuf {
|
||||
if let Ok(d) = std::env::var("GUARA_CONFIG_DIR") {
|
||||
if !d.is_empty() {
|
||||
return PathBuf::from(d);
|
||||
}
|
||||
}
|
||||
#[cfg(unix)]
|
||||
{
|
||||
if let Some(home) = invoking_user_home() {
|
||||
return default_dir(home);
|
||||
}
|
||||
}
|
||||
default_dir(PathBuf::from(
|
||||
std::env::var("HOME")
|
||||
.or_else(|_| std::env::var("USERPROFILE"))
|
||||
.unwrap_or_default(),
|
||||
))
|
||||
}
|
||||
|
||||
fn default_dir(home: PathBuf) -> PathBuf {
|
||||
#[cfg(windows)]
|
||||
{
|
||||
if let Ok(a) = std::env::var("APPDATA") {
|
||||
return PathBuf::from(a).join("Guara");
|
||||
}
|
||||
home.join("AppData").join("Roaming").join("Guara")
|
||||
}
|
||||
#[cfg(target_os = "macos")]
|
||||
{
|
||||
home.join("Library")
|
||||
.join("Application Support")
|
||||
.join("Guara")
|
||||
}
|
||||
#[cfg(all(unix, not(target_os = "macos")))]
|
||||
{
|
||||
match std::env::var("XDG_CONFIG_HOME") {
|
||||
Ok(x)
|
||||
if !x.is_empty()
|
||||
&& std::env::var("SUDO_USER").is_err()
|
||||
&& std::env::var("PKEXEC_UID").is_err() =>
|
||||
{
|
||||
PathBuf::from(x).join("guara")
|
||||
}
|
||||
_ => home.join(".config").join("guara"),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// Se somos root por sudo/pkexec, a home de quem invocou.
|
||||
#[cfg(unix)]
|
||||
fn invoking_user_home() -> Option<PathBuf> {
|
||||
// SAFETY: geteuid não tem pré-condições.
|
||||
if unsafe { libc::geteuid() } != 0 {
|
||||
return None;
|
||||
}
|
||||
let user = std::env::var("SUDO_USER").ok().filter(|u| u != "root");
|
||||
let uid = std::env::var("PKEXEC_UID").ok();
|
||||
let passwd = std::fs::read_to_string("/etc/passwd").ok()?;
|
||||
for l in passwd.lines() {
|
||||
let f: Vec<&str> = l.split(':').collect();
|
||||
if f.len() >= 6 && (user.as_deref() == Some(f[0]) || uid.as_deref() == Some(f[2])) {
|
||||
return Some(PathBuf::from(f[5]));
|
||||
}
|
||||
}
|
||||
None
|
||||
}
|
||||
|
||||
fn file() -> PathBuf {
|
||||
config_dir().join("settings.json")
|
||||
}
|
||||
|
||||
pub fn load() -> Settings {
|
||||
std::fs::read(file())
|
||||
.ok()
|
||||
.and_then(|b| serde_json::from_slice(&b).ok())
|
||||
.unwrap_or_default()
|
||||
}
|
||||
|
||||
pub fn save(s: &Settings) -> Result<()> {
|
||||
let dir = config_dir();
|
||||
std::fs::create_dir_all(&dir)?;
|
||||
let path = file();
|
||||
std::fs::write(&path, serde_json::to_vec_pretty(s)?)?;
|
||||
#[cfg(unix)]
|
||||
{
|
||||
// Como root, devolve a posse ao dono da pasta para o app normal conseguir regravar.
|
||||
use std::os::unix::fs::MetadataExt;
|
||||
if unsafe { libc::geteuid() } == 0 {
|
||||
if let Ok(m) = std::fs::metadata(&dir) {
|
||||
let _ = std::os::unix::fs::chown(&path, Some(m.uid()), Some(m.gid()));
|
||||
}
|
||||
}
|
||||
}
|
||||
Ok(())
|
||||
}
|
||||
Reference in new issue
Block a user