use super::query::QueryKey;
use super::query::QueryProvider;
use crate::models::context::ContextModel;
use crate::utils;
use anyhow::Result;
use base64::Engine;
use std::path::Path;
pub struct ImageProvider {
raw_value: Option<String>,
}
impl ImageProvider {
pub fn new(raw_value: Option<String>) -> Self {
Self { raw_value }
}
fn is_image_file(path: &Path) -> bool {
if let Some(ext) = path.extension().and_then(|e| e.to_str()) {
return matches!(
ext.to_lowercase().as_str(),
"png" | "jpg" | "jpeg" | "gif" | "webp" | "bmp"
);
}
false
}
fn encode_file_to_base64(path: &Path) -> Result<String> {
let bytes = std::fs::read(path)?;
Ok(base64::engine::general_purpose::STANDARD.encode(&bytes))
}
}
impl QueryProvider for ImageProvider {
fn key(&self) -> QueryKey {
QueryKey::Image
}
fn resolve(&self) -> Result<ContextModel> {
if let Some(raw) = self.raw_value.as_deref().filter(|v| !v.trim().is_empty()) {
let paths = utils::clipboard::parse_uri_list(raw);
if let Some(first_path) = paths.first() {
if let Ok(path) = utils::path::resolve(first_path) {
if path.is_file() && Self::is_image_file(&path) {
return Ok(ContextModel::String(Self::encode_file_to_base64(&path)?));
}
}
}
return Ok(ContextModel::String(raw.trim().to_string()));
}
let file_paths = utils::clipboard::clipboard_file_paths();
if let Some(first_path) = file_paths.first() {
if let Ok(path) = utils::path::resolve(first_path) {
if path.is_file() && Self::is_image_file(&path) {
return Ok(ContextModel::String(Self::encode_file_to_base64(&path)?));
}
}
}
match utils::clipboard::read_image_png_base64() {
Some(base64) => Ok(ContextModel::String(base64)),
None => Ok(ContextModel::String(String::new())),
}
}
}