fix: Vietnamese mode default, Flatpak tray UX, Cinnamon menu entry
- Change start_enabled default to true (Vietnamese active on launch) - Tray: detect Flatpak sandbox, skip pointless password prompt - Tray: write first-launch flag file always (not just after sudo) - Desktop file: StartupNotify=true, wider categories for Cinnamon menu - Update tests for new default, README config example
This commit is contained in:
parent
98ce9def79
commit
7d0b2e520c
5 changed files with 35 additions and 21 deletions
|
|
@ -23,6 +23,14 @@
|
||||||
|
|
||||||
### Active Window Detection (Flatpak fix)
|
### Active Window Detection (Flatpak fix)
|
||||||
- **Native X11 `_NET_ACTIVE_WINDOW` query** via `dlopen("libX11.so.6")` — added as third fallback in `get_active_window_id()`. Works inside the Flatpak sandbox where `xdotool`/`xprop` are unavailable. No subprocess, no external dependencies.
|
- **Native X11 `_NET_ACTIVE_WINDOW` query** via `dlopen("libX11.so.6")` — added as third fallback in `get_active_window_id()`. Works inside the Flatpak sandbox where `xdotool`/`xprop` are unavailable. No subprocess, no external dependencies.
|
||||||
|
### Default Mode
|
||||||
|
- **`start_enabled` now defaults to `true`** — Vietnamese mode is active immediately after launch. Press Ctrl+Space to toggle to English.
|
||||||
|
*(Existing users with a custom config.toml are unaffected — the explicit setting overrides the default.)*
|
||||||
|
|
||||||
|
### Tray & Desktop Entry
|
||||||
|
- **No password prompt inside Flatpak** — `needs_root()` detects Flatpak sandbox (`FLATPAK_ID` or `/app/bin` presence) and skips sudo entirely; the sandbox already has device access via `--device=all`.
|
||||||
|
- **First-launch flag always written** — the `.first-launch-done` marker is created even when the password prompt is dismissed, preventing repeated prompts.
|
||||||
|
- **Desktop categories** widened to `Utility;TextTools;X-GNOME-Utilities;` for better visibility in Cinnamon/Mint app menu.
|
||||||
- **Bundle**: `VietPlus-0.1.5.flatpak` (66 MB with tray, runtime `org.gnome.Platform//50`). Warning-free build.
|
- **Bundle**: `VietPlus-0.1.5.flatpak` (66 MB with tray, runtime `org.gnome.Platform//50`). Warning-free build.
|
||||||
|
|
||||||
---
|
---
|
||||||
|
|
|
||||||
|
|
@ -314,7 +314,7 @@ Config file: `~/.config/vietc/config.toml` or `./vietc.toml`
|
||||||
```toml
|
```toml
|
||||||
input_method = "vni" # "vni" or "telex"
|
input_method = "vni" # "vni" or "telex"
|
||||||
toggle_key = "space" # Ctrl+Space to toggle
|
toggle_key = "space" # Ctrl+Space to toggle
|
||||||
start_enabled = false # English by default
|
start_enabled = true # Vietnamese by default
|
||||||
grab = true # grab keyboard (evdev)
|
grab = true # grab keyboard (evdev)
|
||||||
|
|
||||||
[auto_restore]
|
[auto_restore]
|
||||||
|
|
|
||||||
|
|
@ -86,7 +86,7 @@ fn default_toggle_key() -> String {
|
||||||
"space".into()
|
"space".into()
|
||||||
}
|
}
|
||||||
fn default_start_enabled() -> bool {
|
fn default_start_enabled() -> bool {
|
||||||
false
|
true
|
||||||
}
|
}
|
||||||
fn default_true() -> bool {
|
fn default_true() -> bool {
|
||||||
true
|
true
|
||||||
|
|
@ -262,7 +262,7 @@ vs = "với"
|
||||||
let config: Config = toml::from_str(toml).unwrap();
|
let config: Config = toml::from_str(toml).unwrap();
|
||||||
assert_eq!(config.input_method, "vni");
|
assert_eq!(config.input_method, "vni");
|
||||||
assert_eq!(config.toggle_key, "shift");
|
assert_eq!(config.toggle_key, "shift");
|
||||||
assert!(!config.start_enabled);
|
assert!(!config.start_enabled); // explicitly set to false in test toml
|
||||||
assert!(!config.auto_restore.enabled);
|
assert!(!config.auto_restore.enabled);
|
||||||
assert!(config.app_state.enabled);
|
assert!(config.app_state.enabled);
|
||||||
assert_eq!(config.app_state.english_apps, vec!["code", "vim"]);
|
assert_eq!(config.app_state.english_apps, vec!["code", "vim"]);
|
||||||
|
|
@ -281,7 +281,7 @@ vs = "với"
|
||||||
let config: Config = toml::from_str(toml).unwrap();
|
let config: Config = toml::from_str(toml).unwrap();
|
||||||
assert_eq!(config.input_method, "vni");
|
assert_eq!(config.input_method, "vni");
|
||||||
assert_eq!(config.toggle_key, "space");
|
assert_eq!(config.toggle_key, "space");
|
||||||
assert!(!config.start_enabled);
|
assert!(config.start_enabled); // default changed to true
|
||||||
assert!(config.auto_restore.enabled);
|
assert!(config.auto_restore.enabled);
|
||||||
assert!(config.app_state.enabled);
|
assert!(config.app_state.enabled);
|
||||||
assert!(!config.app_state.english_apps.is_empty());
|
assert!(!config.app_state.english_apps.is_empty());
|
||||||
|
|
@ -296,7 +296,7 @@ input_method = "vni"
|
||||||
let config: Config = toml::from_str(toml).unwrap();
|
let config: Config = toml::from_str(toml).unwrap();
|
||||||
assert_eq!(config.input_method, "vni");
|
assert_eq!(config.input_method, "vni");
|
||||||
assert_eq!(config.toggle_key, "space"); // default
|
assert_eq!(config.toggle_key, "space"); // default
|
||||||
assert!(!config.start_enabled); // default
|
assert!(config.start_enabled); // default changed to true
|
||||||
}
|
}
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
|
|
|
||||||
|
|
@ -52,7 +52,8 @@ Exec=/app/bin/vietc-tray
|
||||||
Icon=io.github.vietc.VietPlus
|
Icon=io.github.vietc.VietPlus
|
||||||
Terminal=false
|
Terminal=false
|
||||||
Type=Application
|
Type=Application
|
||||||
Categories=Utility;
|
StartupNotify=true
|
||||||
|
Categories=Utility;TextTools;X-GNOME-Utilities;
|
||||||
END
|
END
|
||||||
|
|
||||||
mkdir -p /app/share/metainfo
|
mkdir -p /app/share/metainfo
|
||||||
|
|
|
||||||
|
|
@ -39,7 +39,16 @@ fn is_daemon_running() -> bool {
|
||||||
check("vietc") || check("vietc-daemon")
|
check("vietc") || check("vietc-daemon")
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fn is_flatpak() -> bool {
|
||||||
|
std::env::var("FLATPAK_ID").is_ok()
|
||||||
|
|| std::path::Path::new("/app/bin").exists()
|
||||||
|
}
|
||||||
|
|
||||||
fn needs_root() -> bool {
|
fn needs_root() -> bool {
|
||||||
|
if is_flatpak() {
|
||||||
|
// Inside Flatpak the sandbox already has device access; sudo won't work.
|
||||||
|
return false;
|
||||||
|
}
|
||||||
let cfg = config::Config::load();
|
let cfg = config::Config::load();
|
||||||
cfg.grab
|
cfg.grab
|
||||||
}
|
}
|
||||||
|
|
@ -114,18 +123,14 @@ fn prompt_password() -> String {
|
||||||
fn start_daemon() {
|
fn start_daemon() {
|
||||||
let daemon_bin = find_sibling_binary("vietc");
|
let daemon_bin = find_sibling_binary("vietc");
|
||||||
|
|
||||||
if needs_root() && !is_daemon_running() {
|
let flag_path = config_path().join(".first-launch-done");
|
||||||
// Mark that we've attempted first launch
|
|
||||||
let flag_path = config_path().join(".first-launch-done");
|
|
||||||
|
|
||||||
if !flag_path.exists() {
|
|
||||||
let password = prompt_password();
|
|
||||||
if password.is_empty() {
|
|
||||||
eprintln!("[vietc-tray] No password provided, starting daemon without root");
|
|
||||||
let _ = std::process::Command::new(&daemon_bin).spawn();
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
if needs_root() && !is_daemon_running() && !flag_path.exists() {
|
||||||
|
let password = prompt_password();
|
||||||
|
if password.is_empty() {
|
||||||
|
eprintln!("[vietc-tray] No password provided, starting daemon without root");
|
||||||
|
let _ = std::process::Command::new(&daemon_bin).spawn();
|
||||||
|
} else {
|
||||||
// Start daemon with sudo
|
// Start daemon with sudo
|
||||||
let mut child = match std::process::Command::new("sudo")
|
let mut child = match std::process::Command::new("sudo")
|
||||||
.args(["-S", &daemon_bin])
|
.args(["-S", &daemon_bin])
|
||||||
|
|
@ -138,6 +143,7 @@ fn start_daemon() {
|
||||||
Err(e) => {
|
Err(e) => {
|
||||||
eprintln!("[vietc-tray] Failed to start daemon with sudo: {}", e);
|
eprintln!("[vietc-tray] Failed to start daemon with sudo: {}", e);
|
||||||
let _ = std::process::Command::new(&daemon_bin).spawn();
|
let _ = std::process::Command::new(&daemon_bin).spawn();
|
||||||
|
let _ = std::fs::write(&flag_path, "1");
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
@ -147,11 +153,10 @@ fn start_daemon() {
|
||||||
let _ = stdin.write_all(format!("{}\n", password).as_bytes());
|
let _ = stdin.write_all(format!("{}\n", password).as_bytes());
|
||||||
}
|
}
|
||||||
let _ = child.wait();
|
let _ = child.wait();
|
||||||
|
|
||||||
// Mark first launch as done
|
|
||||||
let _ = std::fs::write(&flag_path, "1");
|
|
||||||
return;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
let _ = std::fs::write(&flag_path, "1");
|
||||||
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
if !is_daemon_running() {
|
if !is_daemon_running() {
|
||||||
|
|
|
||||||
Loading…
Reference in a new issue