feat: add support for additional MIME types in image processing
This commit is contained in:
@@ -4,6 +4,7 @@ use tracing::{debug, info, trace};
|
||||
pub fn process_once(
|
||||
provider: &dyn ClipboardProvider,
|
||||
opts: &ShrinkOptions,
|
||||
extra_mimes: &[String],
|
||||
last_hash: &mut Option<[u8; 32]>,
|
||||
) -> Result<(), Box<dyn std::error::Error>> {
|
||||
let (data, mime_type) = match provider.capture() {
|
||||
@@ -38,10 +39,15 @@ pub fn process_once(
|
||||
result.mime_type
|
||||
);
|
||||
|
||||
provider.distribute(&[(&result.data, result.mime_type.as_str())])?;
|
||||
// Primary MIME type first, then any aliases the user wants to lie about.
|
||||
let mut items: Vec<(&[u8], &str)> = vec![(&result.data, result.mime_type.as_str())];
|
||||
for alias in extra_mimes {
|
||||
if alias != &result.mime_type {
|
||||
items.push((&result.data, alias.as_str()));
|
||||
}
|
||||
}
|
||||
provider.distribute(&items)?;
|
||||
|
||||
// Track hash of OUTPUT. After distributing webp-only, next capture will
|
||||
// find image/webp (from our subprocess) → same hash → skip. No loop.
|
||||
*last_hash = Some(image_hash(&result.data));
|
||||
Ok(())
|
||||
}
|
||||
|
||||
@@ -17,6 +17,7 @@ async fn main() {
|
||||
};
|
||||
|
||||
let poll = Duration::from_millis(cfg.general.poll_ms);
|
||||
let extra_mimes = cfg.general.extra_mimes.clone();
|
||||
let opts = ShrinkOptions {
|
||||
quality: cfg.general.quality,
|
||||
target_format: cfg.general.format.into(),
|
||||
@@ -27,7 +28,7 @@ async fn main() {
|
||||
|
||||
info!("k-shrink daemon started (poll={}ms)", cfg.general.poll_ms);
|
||||
loop {
|
||||
if let Err(e) = k_shrink::process_once(&backend, &opts, &mut last_hash) {
|
||||
if let Err(e) = k_shrink::process_once(&backend, &opts, &extra_mimes, &mut last_hash) {
|
||||
error!("error: {e}");
|
||||
}
|
||||
tokio::time::sleep(poll).await;
|
||||
|
||||
@@ -59,7 +59,7 @@ fn image_bytes_are_shrunk_and_distributed_as_webp() {
|
||||
let mock = MockClipboard::new(png, "image/png");
|
||||
let mut last_hash = None;
|
||||
|
||||
process_once(&mock, &webp_opts(), &mut last_hash).unwrap();
|
||||
process_once(&mock, &webp_opts(), &[], &mut last_hash).unwrap();
|
||||
|
||||
let dist = mock.distributed.lock().unwrap();
|
||||
assert_eq!(dist.len(), 1, "exactly one item distributed");
|
||||
@@ -74,14 +74,14 @@ fn same_webp_output_not_reprocessed() {
|
||||
let mock = MockClipboard::new(png, "image/png");
|
||||
let mut last_hash = None;
|
||||
|
||||
process_once(&mock, &webp_opts(), &mut last_hash).unwrap();
|
||||
process_once(&mock, &webp_opts(), &[], &mut last_hash).unwrap();
|
||||
|
||||
// After distributing, our subprocess serves image/webp.
|
||||
// Simulate next tick: clipboard returns the webp we just wrote.
|
||||
let webp_data = mock.distributed.lock().unwrap()[0].0.clone();
|
||||
let mock2 = MockClipboard::new(webp_data, "image/webp");
|
||||
|
||||
process_once(&mock2, &webp_opts(), &mut last_hash).unwrap();
|
||||
process_once(&mock2, &webp_opts(), &[], &mut last_hash).unwrap();
|
||||
|
||||
// hash(webp) == last_hash → skipped
|
||||
assert_eq!(mock2.distributed.lock().unwrap().len(), 0);
|
||||
@@ -94,7 +94,7 @@ fn non_image_mime_not_processed() {
|
||||
let mock = MockClipboard::new(b"hello world".to_vec(), "text/plain");
|
||||
let mut last_hash = None;
|
||||
|
||||
process_once(&mock, &webp_opts(), &mut last_hash).unwrap();
|
||||
process_once(&mock, &webp_opts(), &[], &mut last_hash).unwrap();
|
||||
|
||||
assert_eq!(mock.distributed.lock().unwrap().len(), 0);
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user