Fix 5 high-risk bugs from 13th audit pass

- cleanup_placeholder now removes 1-byte marker files on error (regression)
- {width}/{height} template vars replaced with "0" when dimensions unavailable
- Text watermark width multiplier 0.6->1.0 to prevent CJK/wide char clipping
- cmd_undo preserves history entries when trash operations fail
- cmd_watch_remove exits on write failure instead of silent discard
This commit is contained in:
2026-03-07 22:27:37 +02:00
parent d1cab8a691
commit e65ed866eb
4 changed files with 40 additions and 12 deletions

View File

@@ -723,10 +723,11 @@ fn paths_are_same(a: &std::path::Path, b: &std::path::Path) -> bool {
}
}
/// Remove a 0-byte placeholder file created by find_unique_path on error.
/// Remove a placeholder file created by find_unique_path on error.
/// Placeholders are either 0-byte (no marker) or 1-byte (marker `~`).
fn cleanup_placeholder(path: &std::path::Path) {
if let Ok(meta) = std::fs::metadata(path) {
if meta.len() == 0 {
if meta.len() <= 1 {
let _ = std::fs::remove_file(path);
}
}

View File

@@ -40,9 +40,15 @@ pub fn apply_template_full(
result = result.replace("{counter}", &counter.to_string());
}
if let Some((w, h)) = dimensions {
result = result.replace("{width}", &w.to_string());
result = result.replace("{height}", &h.to_string());
match dimensions {
Some((w, h)) => {
result = result.replace("{width}", &w.to_string());
result = result.replace("{height}", &h.to_string());
}
None => {
result = result.replace("{width}", "0");
result = result.replace("{height}", "0");
}
}
// {date} - today's date

View File

@@ -168,7 +168,7 @@ fn render_text_to_image(
opacity: f32,
) -> image::RgbaImage {
let scale = ab_glyph::PxScale::from(font_size);
let text_width = ((text.chars().count().min(10_000) as f32 * font_size.min(1000.0) * 0.6) as u32).saturating_add(4).min(8192);
let text_width = ((text.chars().count().min(10_000) as f32 * font_size.min(1000.0) * 1.0) as u32).saturating_add(4).min(16384);
let text_height = ((font_size.min(1000.0) * 1.4) as u32).saturating_add(4).min(4096);
let alpha = (opacity * 255.0).clamp(0.0, 255.0) as u8;
@@ -266,7 +266,7 @@ fn apply_text_watermark(
} else {
// No rotation - draw text directly (faster)
let scale = ab_glyph::PxScale::from(font_size);
let text_width = ((text.chars().count().min(10_000) as f32 * font_size.min(1000.0) * 0.6) as u32).saturating_add(4).min(8192);
let text_width = ((text.chars().count().min(10_000) as f32 * font_size.min(1000.0) * 1.0) as u32).saturating_add(4).min(16384);
let text_height = ((font_size.min(1000.0) * 1.4) as u32).saturating_add(4).min(4096);
let text_dims = Dimensions {
width: text_width,
@@ -336,7 +336,7 @@ fn apply_tiled_text_watermark(
let alpha = (opacity * 255.0).clamp(0.0, 255.0) as u8;
let draw_color = Rgba([color[0], color[1], color[2], alpha]);
let text_width = ((text.chars().count().min(10_000) as f32 * font_size.min(1000.0) * 0.6) as i64 + 4).min(8192);
let text_width = ((text.chars().count().min(10_000) as f32 * font_size.min(1000.0) * 1.0) as i64 + 4).min(16384);
let text_height = ((font_size.min(1000.0) * 1.4) as i64 + 4).min(4096);
let mut y = spacing as i64;