use crate::cli::EditArgs;
use anyhow::{Context, Result};
use std::path::Path;
pub struct DesktopFile;
impl DesktopFile {
#[allow(clippy::too_many_arguments)]
pub fn create(
path: &Path,
name: &str,
url: &str,
icon: &str,
category: &str,
codename: &str,
exec: &str,
private_window: bool,
) -> Result<()> {
let content = format!(
r#"[Desktop Entry]
Version=1.0
Name={name}
Comment=Web App
Exec={exec}
Terminal=false
Type=Application
Icon={icon}
Categories=GTK;{category};
MimeType=text/html;text/xml;application/xhtml_xml;
StartupWMClass=WebApp-{codename}
StartupNotify=true
X-WebApp-Browser=Firefox
X-WebApp-URL={url}
X-WebApp-PrivateWindow={private_window}
X-WebApp-Isolated=true
"#,
private_window = if private_window { "true" } else { "false" },
);
std::fs::write(path, content).context("Failed to write desktop file")?;
#[cfg(unix)]
{
use std::os::unix::fs::PermissionsExt;
let mut perms = std::fs::metadata(path)?.permissions();
perms.set_mode(0o644);
std::fs::set_permissions(path, perms)?;
}
Ok(())
}
pub fn edit(path: &Path, args: EditArgs) -> Result<()> {
let content = std::fs::read_to_string(path).context("Failed to read desktop file")?;
let mut lines: Vec<String> = content.lines().map(|l| l.to_string()).collect();
if let Some(name) = args.name {
Self::replace_line(&mut lines, "Name", &name);
}
if let Some(url) = args.url {
Self::replace_line(&mut lines, "X-WebApp-URL", &url);
}
if let Some(icon) = args.icon {
Self::replace_line(&mut lines, "Icon", &icon);
}
if let Some(private_window) = args.private_window {
let value = if private_window { "true" } else { "false" };
Self::replace_line(&mut lines, "X-WebApp-PrivateWindow", value);
}
std::fs::write(path, lines.join("\n")).context("Failed to write desktop file")?;
Ok(())
}
fn replace_line(lines: &mut [String], prefix: &str, value: &str) {
for line in lines.iter_mut() {
if line.starts_with(&format!("{}=", prefix)) {
*line = format!("{}={}", prefix, value);
return;
}
}
}
pub fn delete(path: &Path) -> Result<()> {
if path.exists() {
std::fs::remove_file(path).context("Failed to delete desktop file")?;
}
Ok(())
}
pub fn get_exec_command(path: &Path) -> Result<String> {
let content = std::fs::read_to_string(path).context("Failed to read desktop file")?;
let exec_line = content
.lines()
.find(|line| line.starts_with("Exec="))
.ok_or_else(|| anyhow::anyhow!("No Exec line found in desktop file"))?;
Ok(exec_line.strip_prefix("Exec=").unwrap_or("").to_string())
}
}