Function bodies 101 total
test_response_parse_success function · rust · L236-L240 (5 LOC)src-tauri/src/ollama.rs
fn test_response_parse_success() {
let json = serde_json::json!({"response": "Hello world", "done": true});
let result = recognize_text_from_response(&json);
assert_eq!(result, Ok("Hello world".to_string()));
}test_response_parse_empty function · rust · L244-L253 (10 LOC)src-tauri/src/ollama.rs
fn test_response_parse_empty() {
let json = serde_json::json!({"response": " ", "done": true});
let result = recognize_text_from_response(&json);
assert!(result.is_err(), "Expected Err for empty response");
let err = result.unwrap_err().to_lowercase();
assert!(
err.contains("empty"),
"Error should contain 'empty'. Got: {err}"
);
}test_response_parse_error_key function · rust · L257-L266 (10 LOC)src-tauri/src/ollama.rs
fn test_response_parse_error_key() {
let json = serde_json::json!({"error": "model not found"});
let result = recognize_text_from_response(&json);
assert!(result.is_err(), "Expected Err for error key in response");
let err = result.unwrap_err().to_lowercase();
assert!(
err.contains("model not found"),
"Error should contain 'model not found'. Got: {err}"
);
}capture_snapshot function · rust · L7-L34 (28 LOC)src-tauri/src/platform.rs
pub fn capture_snapshot() -> Result<(Vec<u8>, u32, u32), String> {
let path = temp_path("snapshot", "png");
#[cfg(target_os = "macos")]
run_capture_command(
Command::new("screencapture")
.arg("-x")
.arg("-t")
.arg("png")
.arg(&path),
"macOS screencapture failed",
)?;
#[cfg(target_os = "linux")]
capture_linux(&path)?;
#[cfg(target_os = "windows")]
capture_windows(&path)?;
let bytes = fs::read(&path).map_err(|error| format!("Failed to read screenshot: {error}"))?;
let image = image::load_from_memory(&bytes)
.map_err(|error| format!("Failed to decode screenshot: {error}"))?;
let (width, height) = image.dimensions();
let _ = fs::remove_file(&path);
Ok((bytes, width, height))
}crop_png function · rust · L35-L52 (18 LOC)src-tauri/src/platform.rs
pub fn crop_png(bytes: &[u8], x: u32, y: u32, width: u32, height: u32) -> Result<Vec<u8>, String> {
let image = image::load_from_memory(bytes)
.map_err(|error| format!("Failed to decode stored snapshot: {error}"))?;
let bounded_width = width.min(image.width().saturating_sub(x));
let bounded_height = height.min(image.height().saturating_sub(y));
if bounded_width == 0 || bounded_height == 0 {
return Err("Selection fell outside the current snapshot.".into());
}
let cropped = image.crop_imm(x, y, bounded_width, bounded_height);
let mut output = std::io::Cursor::new(Vec::new());
cropped
.write_to(&mut output, ImageFormat::Png)
.map_err(|error| format!("Failed to encode crop: {error}"))?;
Ok(output.into_inner())
}temp_path function · rust · L53-L60 (8 LOC)src-tauri/src/platform.rs
fn temp_path(prefix: &str, extension: &str) -> PathBuf {
let timestamp = SystemTime::now()
.duration_since(UNIX_EPOCH)
.unwrap_or_default()
.as_millis();
std::env::temp_dir().join(format!("{prefix}-{timestamp}.{extension}"))
}run_capture_command function · rust · L61-L75 (15 LOC)src-tauri/src/platform.rs
fn run_capture_command(command: &mut Command, error_prefix: &str) -> Result<(), String> {
let output = command
.output()
.map_err(|error| format!("{error_prefix}: {error}"))?;
if output.status.success() {
Ok(())
} else {
Err(format!(
"{error_prefix}: {}",
String::from_utf8_lossy(&output.stderr).trim()
))
}
}Want this analysis on your repo? https://repobility.com/scan/
capture_linux function · rust · L78-L112 (35 LOC)src-tauri/src/platform.rs
fn capture_linux(path: &Path) -> Result<(), String> {
let mut attempts = vec![
{
let mut command = Command::new("grim");
command.arg("-t").arg("png").arg(path);
command
},
{
let mut command = Command::new("gnome-screenshot");
command.arg("-f").arg(path);
command
},
{
let mut command = Command::new("import");
command.arg("-window").arg("root").arg(path);
command
},
];
let mut last_error = None;
for attempt in attempts.iter_mut() {
match attempt.output() {
Ok(output) if output.status.success() => return Ok(()),
Ok(output) => {
last_error = Some(String::from_utf8_lossy(&output.stderr).trim().to_string())
}
Err(error) => last_error = Some(error.to_string()),
}
}
Err(format!(
"No Linux screenshot backend succeeded. Tried grimcapture_windows function · rust · L115-L136 (22 LOC)src-tauri/src/platform.rs
fn capture_windows(path: &Path) -> Result<(), String> {
let escaped_path = path.to_string_lossy().replace('\'', "''");
let script = format!(
"Add-Type -AssemblyName System.Windows.Forms; \
Add-Type -AssemblyName System.Drawing; \
$bounds = [System.Windows.Forms.SystemInformation]::VirtualScreen; \
$bitmap = New-Object System.Drawing.Bitmap $bounds.Width, $bounds.Height; \
$graphics = [System.Drawing.Graphics]::FromImage($bitmap); \
$graphics.CopyFromScreen($bounds.X, $bounds.Y, 0, 0, $bitmap.Size); \
$bitmap.Save('{escaped_path}', [System.Drawing.Imaging.ImageFormat]::Png); \
$graphics.Dispose(); \
$bitmap.Dispose();"
);
run_capture_command(
Command::new("powershell")
.arg("-NoProfile")
.arg("-Command")
.arg(script),
"Windows PowerShell screen capture failed",
)
}png_dimensions function · rust · L139-L143 (5 LOC)src-tauri/src/platform.rs
pub fn png_dimensions(bytes: &[u8]) -> Result<(u32, u32), String> {
let image = image::load_from_memory(bytes)
.map_err(|error| format!("Failed to decode PNG dimensions: {error}"))?;
Ok(image.dimensions())
}decode_png function · rust · L146-L148 (3 LOC)src-tauri/src/platform.rs
pub fn decode_png(bytes: &[u8]) -> Result<DynamicImage, String> {
image::load_from_memory(bytes).map_err(|error| format!("Failed to decode PNG: {error}"))
}to_payload function · rust · L42-L49 (8 LOC)src-tauri/src/state.rs
pub fn to_payload(&self) -> SnapshotPayload {
SnapshotPayload {
id: self.id,
width: self.width,
height: self.height,
data_url: format!("data:image/png;base64,{}", STANDARD.encode(&self.png_bytes)),
}
}from function · rust · L87-L98 (12 LOC)src-tauri/src/state.rs
fn from(value: &StoredSegment) -> Self {
Self {
id: value.id,
order: value.order,
snapshot_id: value.snapshot_id,
selection: value.selection.clone(),
recognized_text: value.recognized_text.clone(),
merge_strategy: value.merge_strategy.as_str().to_string(),
overlap_lines: value.overlap_lines,
created_at_epoch_ms: value.created_at_epoch_ms,
}
}to_payload function · rust · L118-L131 (14 LOC)src-tauri/src/state.rs
pub fn to_payload(&self) -> AppStatePayload {
AppStatePayload {
merged_text: self.merged_text.clone(),
segments: self.segments.iter().map(SegmentPayload::from).collect(),
current_snapshot: self
.current_snapshot
.as_ref()
.map(|snapshot| SnapshotSummary {
id: snapshot.id,
width: snapshot.width,
height: snapshot.height,
}),
}
}clear function · rust · L132-L137 (6 LOC)src-tauri/src/state.rs
pub fn clear(&mut self) {
self.current_snapshot = None;
self.segments.clear();
self.merged_text.clear();
}All rows scored by the Repobility analyzer (https://repobility.com)
store_snapshot function · rust · L138-L155 (18 LOC)src-tauri/src/state.rs
pub fn store_snapshot(
&mut self,
png_bytes: Vec<u8>,
width: u32,
height: u32,
) -> SnapshotPayload {
self.next_snapshot_id += 1;
let snapshot = StoredSnapshot {
id: self.next_snapshot_id,
png_bytes,
width,
height,
};
let payload = snapshot.to_payload();
self.current_snapshot = Some(snapshot);
payload
}push_segment function · rust · L156-L175 (20 LOC)src-tauri/src/state.rs
pub fn push_segment(
&mut self,
snapshot_id: u64,
selection: SelectionRect,
recognized_text: String,
) {
self.next_segment_id += 1;
self.segments.push(StoredSegment {
id: self.next_segment_id,
order: self.segments.len() + 1,
snapshot_id,
selection,
recognized_text,
merge_strategy: MergeStrategy::Initial,
overlap_lines: 0,
created_at_epoch_ms: now_epoch_ms(),
});
self.rebuild_merge();
}undo_last_segment function · rust · L176-L180 (5 LOC)src-tauri/src/state.rs
pub fn undo_last_segment(&mut self) {
self.segments.pop();
self.rebuild_merge();
}rebuild_merge function · rust · L181-L193 (13 LOC)src-tauri/src/state.rs
fn rebuild_merge(&mut self) {
let mut merged_text = String::new();
for segment in &mut self.segments {
let outcome = append_text(&merged_text, &segment.recognized_text);
segment.merge_strategy = outcome.strategy;
segment.overlap_lines = outcome.overlap_lines;
merged_text = outcome.merged_text;
}
self.merged_text = merged_text;
}now_epoch_ms function · rust · L195-L201 (7 LOC)src-tauri/src/state.rs
fn now_epoch_ms() -> u128 {
SystemTime::now()
.duration_since(UNIX_EPOCH)
.unwrap_or_default()
.as_millis()
}update_tray_icon function · rust · L12-L34 (23 LOC)src-tauri/src/tray_badge.rs
pub fn update_tray_icon(app: &AppHandle, count: usize) {
let Some(tray) = app.tray_by_id("main") else {
return;
};
if count == 0 {
let icon = tauri::include_image!("./icons/icon.png");
let _ = tray.set_icon(Some(icon));
let _ = tray.set_icon_as_template(true);
return;
}
match render_badged_icon(count) {
Ok((rgba, width, height)) => {
let icon = TauriImage::new_owned(rgba, width, height);
let _ = tray.set_icon(Some(icon));
let _ = tray.set_icon_as_template(false);
}
Err(e) => {
eprintln!("[JFC tray_badge] Failed to render badge: {e}");
}
}
}render_badged_icon function · rust · L39-L113 (75 LOC)src-tauri/src/tray_badge.rs
fn render_badged_icon(count: usize) -> Result<(Vec<u8>, u32, u32), String> {
let base_img = image::load_from_memory(BASE_ICON)
.map_err(|e| format!("Failed to decode base icon: {e}"))?
.into_rgba8();
let icon_size = base_img.width(); // 128
// Badge radius: 60% of icon size so it dominates at small tray sizes
let badge_r = (icon_size as f64 * 0.60) as i32; // ~77px on 128px icon
let border_w = 4i32;
// Canvas must be large enough to hold icon + badge overflow.
// Badge center sits on the icon's bottom-right corner.
// Badge extends badge_r pixels past that corner in each direction.
let canvas_size = icon_size + badge_r as u32 + border_w as u32;
let mut canvas = RgbaImage::new(canvas_size, canvas_size);
// Copy base icon onto canvas at (0, 0)
for y in 0..base_img.height() {
for x in 0..base_img.width() {
canvas.put_pixel(x, y, *base_img.get_pixel(x, y));
}
}
// Badge center: on the bcanvas_is_larger_than_base_icon function · rust · L120-L126 (7 LOC)src-tauri/src/tray_badge.rs
fn canvas_is_larger_than_base_icon() {
let (_, w, h) = render_badged_icon(1).expect("should render");
// Canvas must be bigger than 128x128 to allow badge overflow
assert!(w > 128, "Canvas width {w} should exceed icon size");
assert!(h > 128, "Canvas height {h} should exceed icon size");
assert_eq!(w, h, "Canvas should be square");
}Repobility · open methodology · https://repobility.com/research/
render_single_digit_badge function · rust · L129-L141 (13 LOC)src-tauri/src/tray_badge.rs
fn render_single_digit_badge() {
let (rgba, w, h) = render_badged_icon(3).expect("should render badge for count=3");
assert_eq!(rgba.len(), (w * h * 4) as usize);
let img = RgbaImage::from_raw(w, h, rgba).unwrap();
// Red pixels should exist in the bottom-right area (badge location)
let has_red = (h / 2..h).any(|y| {
(w / 2..w).any(|x| {
let p = img.get_pixel(x, y);
p[0] > 200 && p[1] < 60 && p[2] < 60
})
});
assert!(has_red, "Badge should contain red pixels in bottom-right");
}render_double_digit_badge function · rust · L144-L147 (4 LOC)src-tauri/src/tray_badge.rs
fn render_double_digit_badge() {
let (rgba, w, h) = render_badged_icon(42).expect("should render badge for count=42");
assert_eq!(rgba.len(), (w * h * 4) as usize);
}render_overflow_badge function · rust · L150-L153 (4 LOC)src-tauri/src/tray_badge.rs
fn render_overflow_badge() {
let (rgba, w, h) = render_badged_icon(150).expect("should render badge for count=150");
assert_eq!(rgba.len(), (w * h * 4) as usize);
}badge_has_white_text function · rust · L156-L169 (14 LOC)src-tauri/src/tray_badge.rs
fn badge_has_white_text() {
let (rgba, w, h) = render_badged_icon(5).expect("should render badge for count=5");
let img = RgbaImage::from_raw(w, h, rgba).unwrap();
// White text pixels in the badge area (bottom-right quadrant, near icon corner)
let badge_zone_y = (h * 3 / 8)..h;
let badge_zone_x = (w * 3 / 8)..w;
let has_white = badge_zone_y.into_iter().any(|y| {
badge_zone_x.clone().any(|x| {
let p = img.get_pixel(x, y);
p[0] > 240 && p[1] > 240 && p[2] > 240 && p[3] > 200
})
});
assert!(has_white, "Badge should contain white text pixels");
}default function · rust · L13-L17 (5 LOC)src-tauri/src/watcher.rs
fn default() -> Self {
Self {
inner: Mutex::new(Vec::new()),
}
}add_pending_file function · rust · L23-L40 (18 LOC)src-tauri/src/watcher.rs
pub fn add_pending_file(&self, path: PathBuf) -> bool {
let ext = path
.extension()
.and_then(|e| e.to_str())
.unwrap_or("")
.to_lowercase();
if ext != "png" && ext != "jpg" && ext != "jpeg" {
return false;
}
let mut guard = self.inner.lock().expect("BatchState lock poisoned");
if guard.contains(&path) {
return false;
}
guard.push(path);
true
}pending_count function · rust · L43-L45 (3 LOC)src-tauri/src/watcher.rs
pub fn pending_count(&self) -> usize {
self.inner.lock().expect("BatchState lock poisoned").len()
}drain_pending function · rust · L48-L51 (4 LOC)src-tauri/src/watcher.rs
pub fn drain_pending(&self) -> Vec<PathBuf> {
let mut guard = self.inner.lock().expect("BatchState lock poisoned");
guard.drain(..).collect()
}Repobility — the code-quality scanner for AI-generated software · https://repobility.com
clear function · rust · L54-L56 (3 LOC)src-tauri/src/watcher.rs
pub fn clear(&self) {
self.inner.lock().expect("BatchState lock poisoned").clear();
}start_watcher function · rust · L65-L128 (64 LOC)src-tauri/src/watcher.rs
pub fn start_watcher(watch_dir: &str, app_handle: AppHandle) -> Result<(), String> {
let expanded = expand_tilde(watch_dir);
let watch_path = PathBuf::from(&expanded);
if !watch_path.exists() {
eprintln!(
"[JFC watcher] Watch directory not found: {}. Watcher not started.",
watch_path.display()
);
return Ok(());
}
let app_handle_clone = app_handle.clone();
let mut watcher = notify::recommended_watcher(move |result: notify::Result<notify::Event>| {
let event = match result {
Ok(e) => e,
Err(e) => {
eprintln!("[JFC watcher] Watch error: {e}");
return;
}
};
let is_relevant = matches!(
event.kind,
EventKind::Create(_)
| EventKind::Modify(notify::event::ModifyKind::Name(
notify::event::RenameMode::To
))
);
if !is_relevant {
expand_tilde function · rust · L129-L137 (9 LOC)src-tauri/src/watcher.rs
fn expand_tilde(path: &str) -> String {
if path.starts_with("~/") || path == "~" {
if let Some(home) = dirs::home_dir() {
return path.replacen("~", &home.to_string_lossy(), 1);
}
}
path.to_string()
}make_path function · rust · L142-L145 (4 LOC)src-tauri/src/watcher.rs
fn make_path(name: &str) -> PathBuf {
PathBuf::from(format!("/tmp/test/{name}"))
}test_add_pending_file_png function · rust · L148-L153 (6 LOC)src-tauri/src/watcher.rs
fn test_add_pending_file_png() {
let state = BatchState::default();
let added = state.add_pending_file(make_path("screenshot.png"));
assert!(added, "Expected .png to be added");
assert_eq!(state.pending_count(), 1);
}test_add_pending_file_dedup function · rust · L156-L164 (9 LOC)src-tauri/src/watcher.rs
fn test_add_pending_file_dedup() {
let state = BatchState::default();
let path = make_path("screenshot.png");
let first = state.add_pending_file(path.clone());
let second = state.add_pending_file(path);
assert!(first, "First addition should return true");
assert!(!second, "Second addition of same path should return false");
assert_eq!(state.pending_count(), 1, "Should still be exactly 1 entry");
}test_add_pending_file_ignores_non_image function · rust · L167-L172 (6 LOC)src-tauri/src/watcher.rs
fn test_add_pending_file_ignores_non_image() {
let state = BatchState::default();
let added = state.add_pending_file(make_path("document.txt"));
assert!(!added, "Expected .txt to be ignored");
assert_eq!(state.pending_count(), 0);
}test_add_pending_file_jpg_and_jpeg function · rust · L175-L182 (8 LOC)src-tauri/src/watcher.rs
fn test_add_pending_file_jpg_and_jpeg() {
let state = BatchState::default();
let jpg_added = state.add_pending_file(make_path("photo.jpg"));
let jpeg_added = state.add_pending_file(make_path("photo2.jpeg"));
assert!(jpg_added, "Expected .jpg to be accepted");
assert!(jpeg_added, "Expected .jpeg to be accepted");
assert_eq!(state.pending_count(), 2);
}Want this analysis on your repo? https://repobility.com/scan/
test_pending_count function · rust · L185-L192 (8 LOC)src-tauri/src/watcher.rs
fn test_pending_count() {
let state = BatchState::default();
assert_eq!(state.pending_count(), 0);
state.add_pending_file(make_path("a.png"));
assert_eq!(state.pending_count(), 1);
state.add_pending_file(make_path("b.jpg"));
assert_eq!(state.pending_count(), 2);
}test_drain_pending function · rust · L195-L203 (9 LOC)src-tauri/src/watcher.rs
fn test_drain_pending() {
let state = BatchState::default();
state.add_pending_file(make_path("a.png"));
state.add_pending_file(make_path("b.jpg"));
let drained = state.drain_pending();
assert_eq!(drained.len(), 2, "Should drain 2 entries");
assert_eq!(state.pending_count(), 0, "List should be empty after drain");
}test_start_watcher_returns_ok_for_existing_dir function · rust · L206-L225 (20 LOC)src-tauri/src/watcher.rs
fn test_start_watcher_returns_ok_for_existing_dir() {
// We can't test the full event loop without an AppHandle,
// but we can verify that start_watcher does not panic on a non-existent dir
// (it should log and return Ok).
let non_existent = "/tmp/jfc_no_such_dir_12345_test";
// This should return Ok(()) with a warning, not an error
// We test expand_tilde and the missing-dir path directly
let expanded = super::expand_tilde(non_existent);
assert_eq!(expanded, non_existent, "Non-tilde path should be unchanged");
// Verify that adding to BatchState from multiple threads is safe
use std::sync::Arc;
let state = Arc::new(BatchState::default());
let state2 = state.clone();
let handle = std::thread::spawn(move || {
state2.add_pending_file(PathBuf::from("/tmp/threaded.png"));
});
handle.join().unwrap();
assert_eq!(state.pending_count(), 1);
}main function · javascript · L20-L25 (6 LOC)ui/app.js
async function main() {
bindEvents();
await refreshAll();
// Re-fetch state whenever the panel regains focus (user switches back from screenshots)
window.addEventListener("focus", refreshAll);
}bindEvents function · javascript · L27-L30 (4 LOC)ui/app.js
function bindEvents() {
elements.processNowButton.addEventListener("click", processNow);
elements.clearBatchButton.addEventListener("click", clearBatch);
}refreshAll function · javascript · L32-L44 (13 LOC)ui/app.js
async function refreshAll() {
try {
const [batchState, appState] = await Promise.all([
invoke("get_batch_state"),
invoke("get_app_state"),
]);
context.batchState = batchState;
context.appState = appState;
render();
} catch (error) {
flash(String(error), true);
}
}processNow function · javascript · L46-L58 (13 LOC)ui/app.js
async function processNow() {
setBusy(elements.processNowButton, true, "Processing...");
try {
await invoke("process_batch_now");
flash("Batch processed — text copied to clipboard.");
elements.clipboardStatus.textContent = "Copied";
await refreshAll();
} catch (error) {
flash(String(error), true);
} finally {
setBusy(elements.processNowButton, false, "Process Now");
}
}clearBatch function · javascript · L60-L71 (12 LOC)ui/app.js
async function clearBatch() {
setBusy(elements.clearBatchButton, true, "Clearing...");
try {
await invoke("clear_batch");
flash("Batch cleared.");
await refreshAll();
} catch (error) {
flash(String(error), true);
} finally {
setBusy(elements.clearBatchButton, false, "Clear Batch");
}
}All rows scored by the Repobility analyzer (https://repobility.com)
render function · javascript · L73-L120 (48 LOC)ui/app.js
function render() {
const { pendingCount, pendingFiles } = context.batchState;
const { mergedText, segments } = context.appState;
elements.pendingCount.textContent = String(pendingCount);
elements.segmentCount.textContent = String(segments.length);
elements.mergedOutput.value = mergedText || "";
elements.processNowButton.disabled = pendingCount === 0;
// Pending file list
if (!pendingFiles.length) {
elements.pendingList.innerHTML = '<p class="empty-state">No screenshots pending.</p>';
} else {
elements.pendingList.innerHTML = pendingFiles
.map((filePath) => {
const filename = filePath.split("/").pop() || filePath;
return `
<article class="segment-card pending-file-card">
<div class="segment-meta">
<span class="segment-badge pending-badge">queued</span>
<span>${escapeHtml(filename)}</span>
</div>
</article>`;
})
.join("");
}
// Session timeline (prosetBusy function · javascript · L122-L125 (4 LOC)ui/app.js
function setBusy(button, busy, label) {
button.disabled = busy;
button.textContent = label;
}flash function · javascript · L128-L138 (11 LOC)ui/app.js
function flash(message, isError = false) {
window.clearTimeout(flashTimer);
elements.flashBanner.hidden = false;
elements.flashBanner.textContent = message;
elements.flashBanner.style.background = isError
? "rgba(122, 22, 22, 0.92)"
: "rgba(31, 28, 23, 0.9)";
flashTimer = window.setTimeout(() => {
elements.flashBanner.hidden = true;
}, 3200);
}