Function bodies 92 total
App function · typescript · L16-L153 (138 LOC)src/App.tsx
export default function App() {
const { view, loadItems, loadSettings, loadTags, showToast, settings } = useStore();
const [onboarded, setOnboarded] = useState<boolean | null>(null);
// Check if onboarding was completed
useEffect(() => {
const done = localStorage.getItem("ri-onboarded");
setOnboarded(done === "true");
loadItems();
loadSettings();
loadTags();
}, []);
useEffect(() => {
if (settings?.language) setLanguage(settings.language);
}, [settings?.language]);
const completeOnboarding = () => {
localStorage.setItem("ri-onboarded", "true");
setOnboarded(true);
};
// ⇧⌘S capture — tries selected text first (no clipboard touch), falls back to clipboard
useEffect(() => {
const unlisten = listen<string>("capture-triggered", async (event) => {
try {
let appName = "Clipboard";
let windowTitle = "";
let urlFromTitle: string | null = null;
let selectedText: string | null = null;
try CaptureOverlay function · typescript · L14-L242 (229 LOC)src/components/CaptureOverlay.tsx
export default function CaptureOverlay() {
const [state, setState] = useState<OverlayState>({ mode: "idle" });
const dismissTimer = useRef<ReturnType<typeof setTimeout> | undefined>(undefined);
const sourceAppRef = useRef(""); // remember source app for refocus
const autoDismiss = (source: string) => {
if (dismissTimer.current) clearTimeout(dismissTimer.current);
dismissTimer.current = setTimeout(async () => {
getCurrentWindow().hide();
setState({ mode: "idle" });
// Refocus source app
if (source) {
invoke("refocus_app", { appName: source }).catch(() => {});
}
}, 4000);
};
// Text + image capture event from Rust
useEffect(() => {
const unlisten = listen<string>("capture-triggered", async (event) => {
try {
let appName = "Clipboard";
let selectedText: string | null = null;
let imagePaths: string[] = [];
try {
if (event.payload) {
const data = JSON.parse(evenInboxPanel function · typescript · L9-L178 (170 LOC)src/components/InboxPanel.tsx
export default function InboxPanel() {
const { items, selectedIds, setView, showArchived, setShowArchived, loadItems, selectAll, clearSelection, archiveSelected, searchQuery } = useStore();
useEffect(() => {
loadItems(showArchived);
}, [showArchived]);
const todayCount = items.filter((i) => {
const d = new Date(i.created_at);
const now = new Date();
return d.toDateString() === now.toDateString();
}).length;
const handleKeyDown = (e: React.KeyboardEvent) => {
if (e.metaKey && e.key === "a") {
e.preventDefault();
selectAll();
}
if (e.metaKey && e.key === "Backspace") {
e.preventDefault();
archiveSelected();
}
};
return (
<div className="flex flex-col h-full" onKeyDown={handleKeyDown} tabIndex={0}>
{/* Title bar: drag + capture buttons + close */}
<div className="flex items-center px-3 pt-2 pb-1 gap-1" data-tauri-drag-region>
<span className="text-xs font-semibold text-[var(--text-secondaryappBadgeColor function · typescript · L15-L18 (4 LOC)src/components/ItemCard.tsx
function appBadgeColor(appName: string): string {
const hash = Array.from(appName).reduce((acc, c) => acc * 31 + c.charCodeAt(0), 0);
return APP_BADGE_COLORS[Math.abs(hash) % APP_BADGE_COLORS.length];
}ItemCard function · typescript · L24-L176 (153 LOC)src/components/ItemCard.tsx
export default function ItemCard({ item }: ItemCardProps) {
const { selectedIds, toggleSelect, expandedId, setExpanded, deleteItem, updateItemTags, showToast } = useStore();
const [showContext, setShowContext] = useState(false);
const isSelected = selectedIds.has(item.id);
const isExpanded = expandedId === item.id;
const time = new Date(item.created_at).toLocaleTimeString([], { hour: "2-digit", minute: "2-digit" });
const preview = item.content.slice(0, 120);
const isImage = item.content_type === "image";
const colorIndex = (name: string) => {
const hash = Array.from(name).reduce((acc, c) => acc * 31 + c.charCodeAt(0), 0);
return Math.abs(hash) % 8;
};
const handleCopy = async () => {
await writeText(item.content);
showToast("Copied");
};
const handleArchive = async () => {
await api.updateItem(item.id, null, null, true);
useStore.getState().loadItems(useStore.getState().showArchived);
};
return (
<div
className={`relatiOnboarding function · typescript · L8-L165 (158 LOC)src/components/Onboarding.tsx
export default function Onboarding({ onComplete }: OnboardingProps) {
const [step, setStep] = useState<"welcome" | "accessibility" | "done">("welcome");
const [axGranted, setAxGranted] = useState(false);
const [checking, setChecking] = useState(false);
const checkAx = useCallback(async () => {
setChecking(true);
try {
const granted = await invoke<boolean>("check_accessibility");
setAxGranted(granted);
// Don't auto-skip — user must confirm they enabled BOTH permissions
} catch {
setAxGranted(false);
}
setChecking(false);
}, [step]);
// Poll for accessibility permission every 2s when on that step
useEffect(() => {
if (step !== "accessibility") return;
checkAx();
const interval = setInterval(checkAx, 2000);
return () => clearInterval(interval);
}, [step, checkAx]);
const openSettings = async () => {
await invoke("open_accessibility_settings");
};
if (step === "welcome") {
return (
<div claPackEditor function · typescript · L11-L195 (185 LOC)src/components/PackEditor.tsx
export default function PackEditor() {
const { editingPack, setEditingPack, showToast, loadPacks, items: allItems } = useStore();
const [title, setTitle] = useState(editingPack?.title || "");
const [description, setDescription] = useState(editingPack?.description || "");
const [constraints, setConstraints] = useState(editingPack?.constraints || "");
const [questions, setQuestions] = useState(editingPack?.questions || "");
const [format, setFormat] = useState<ExportFormat>((editingPack?.export_format as ExportFormat) || "markdown");
const [itemIds, setItemIds] = useState<string[]>(editingPack?.item_ids || []);
const [packItems, setPackItems] = useState<CaptureItem[]>([]);
useEffect(() => {
// Load the actual items for the pack
const loadPackItems = async () => {
const loaded = await api.listItems(0, 200, false, null, null);
const filtered = loaded.filter((i) => itemIds.includes(i.id));
// Maintain order from itemIds
const ordered = itemRepobility · severity-and-effort ranking · https://repobility.com
PacksList function · typescript · L7-L89 (83 LOC)src/components/PacksList.tsx
export default function PacksList() {
const { packs, loadPacks, setEditingPack, deletePack, setView, showToast } = useStore();
useEffect(() => {
loadPacks();
}, []);
const handleExport = async (id: string, format: string) => {
const exported = await api.exportPack(id, format);
await writeText(exported);
showToast(`✓ ${t("pack_copied", { count: 0 })}`);
};
return (
<div className="flex flex-col h-full">
{/* Header */}
<div className="px-3 py-2 border-b border-[var(--border)] flex items-center gap-2">
<button
onClick={() => setView("inbox")}
className="px-2 py-0.5 rounded text-[11px] text-[var(--text-secondary)] hover:bg-[var(--bg-secondary)]"
>
{t("inbox")}
</button>
<button
className="px-2 py-0.5 rounded text-[11px] font-medium bg-[var(--accent)] text-white"
>
{t("packs")}
</button>
</div>
{/* Pack list */}
<div className="fSearchBar function · typescript · L5-L67 (63 LOC)src/components/SearchBar.tsx
export default function SearchBar() {
const { searchQuery, setSearchQuery, searchItems, loadItems, showArchived } = useStore();
const [localQuery, setLocalQuery] = useState(searchQuery);
const timerRef = useRef<ReturnType<typeof setTimeout> | undefined>(undefined);
const inputRef = useRef<HTMLInputElement>(null);
useEffect(() => {
clearTimeout(timerRef.current);
timerRef.current = setTimeout(() => {
setSearchQuery(localQuery);
if (localQuery.trim()) {
searchItems(localQuery);
} else {
loadItems(showArchived);
}
}, 150);
return () => clearTimeout(timerRef.current);
}, [localQuery]);
// Auto-focus search on panel open (Maccy pattern: search-on-open)
useEffect(() => {
inputRef.current?.focus();
const handleFocus = () => inputRef.current?.focus();
window.addEventListener("focus", handleFocus);
return () => window.removeEventListener("focus", handleFocus);
}, []);
useEffect(() => {
const handlSettings function · typescript · L7-L145 (139 LOC)src/components/Settings.tsx
export default function Settings() {
const { settings, loadSettings, setView, showToast } = useStore();
const [local, setLocal] = useState<AppSettings | null>(null);
useEffect(() => {
if (settings) setLocal({ ...settings });
}, [settings]);
if (!local) return null;
const update = <K extends keyof AppSettings>(key: K, value: AppSettings[K]) => {
setLocal({ ...local, [key]: value });
};
const handleSave = async () => {
try {
await api.updateSettings(local);
await loadSettings();
showToast(`✓ ${t("save")}`);
setView("inbox");
} catch {
showToast("Error saving settings");
}
};
return (
<div className="flex flex-col h-full">
{/* Header */}
<div className="px-3 py-2 border-b border-[var(--border)] flex items-center gap-2">
<button onClick={() => setView("inbox")} className="text-[var(--text-secondary)] hover:text-[var(--text)]">
<svg className="w-4 h-4" fill="none" stroke="currentColoSettingRow function · typescript · L147-L154 (8 LOC)src/components/Settings.tsx
function SettingRow({ label, children }: { label: string; children: React.ReactNode }) {
return (
<div>
<div className="text-[11px] text-[var(--text-secondary)] mb-1 font-medium">{label}</div>
{children}
</div>
);
}TagInput function · typescript · L11-L98 (88 LOC)src/components/TagInput.tsx
export default function TagInput({ value, onChange }: TagInputProps) {
const [input, setInput] = useState("");
const [suggestions, setSuggestions] = useState<{ name: string; color_index: number }[]>([]);
const [showSuggestions, setShowSuggestions] = useState(false);
const { tags, loadTags } = useStore();
const inputRef = useRef<HTMLInputElement>(null);
useEffect(() => {
if (input.length > 0) {
loadTags(input);
setShowSuggestions(true);
} else {
setShowSuggestions(false);
}
}, [input]);
useEffect(() => {
setSuggestions(tags.filter((tag) => !value.includes(tag.name)));
}, [tags, value]);
const addTag = (tagName: string) => {
const normalized = tagName.toLowerCase().replace(/\s+/g, "-").replace(/[^a-z0-9-]/g, "").slice(0, 30);
if (normalized && !value.includes(normalized)) {
onChange([...value, normalized]);
}
setInput("");
setShowSuggestions(false);
};
const removeTag = (tagName: string) => {
onChToast function · typescript · L3-L14 (12 LOC)src/components/Toast.tsx
export default function Toast() {
const { toast } = useStore();
if (!toast.visible) return null;
return (
<div className="fixed top-3 left-1/2 -translate-x-1/2 z-50">
<div className="bg-gray-900 text-white px-4 py-2.5 rounded-lg shadow-lg text-sm font-medium max-w-[340px] truncate">
{toast.message}
</div>
</div>
);
}setLanguage function · typescript · L8-L10 (3 LOC)src/lib/i18n.ts
export function setLanguage(lang: string) {
currentLang = lang;
}t function · typescript · L12-L21 (10 LOC)src/lib/i18n.ts
export function t(key: string, params?: Record<string, string | number>): string {
const dict = translations[currentLang] || translations.en;
let text = dict[key] || translations.en[key] || key;
if (params) {
for (const [k, v] of Object.entries(params)) {
text = text.replace(`{${k}}`, String(v));
}
}
return text;
}Generated by Repobility's multi-pass static-analysis pipeline (https://repobility.com)
getLanguage function · typescript · L23-L25 (3 LOC)src/lib/i18n.ts
export function getLanguage(): string {
return currentLang;
}main function · rust · L1-L3 (3 LOC)src-tauri/build.rs
fn main() {
tauri_build::build()
}row_to_item function · rust · L9-L27 (19 LOC)src-tauri/src/commands.rs
fn row_to_item(row: &rusqlite::Row) -> rusqlite::Result<CaptureItem> {
let tags_str: String = row.get(6)?;
let tags: Vec<String> = serde_json::from_str(&tags_str).unwrap_or_default();
let is_archived: i32 = row.get(8)?;
Ok(CaptureItem {
id: row.get(0)?,
content: row.get(1)?,
content_type: row.get(2)?,
source_app: row.get(3)?,
source_url: row.get(4)?,
source_title: row.get(5)?,
tags,
char_count: row.get(7)?,
is_archived: is_archived != 0,
created_at: row.get(9)?,
updated_at: row.get(10)?,
})
}row_to_tag function · rust · L28-L36 (9 LOC)src-tauri/src/commands.rs
fn row_to_tag(row: &rusqlite::Row) -> rusqlite::Result<Tag> {
Ok(Tag {
name: row.get(0)?,
use_count: row.get(1)?,
last_used_at: row.get(2)?,
color_index: row.get(3)?,
})
}row_to_pack function · rust · L37-L52 (16 LOC)src-tauri/src/commands.rs
fn row_to_pack(row: &rusqlite::Row) -> rusqlite::Result<ContextPack> {
let item_ids_str: String = row.get(5)?;
let item_ids: Vec<String> = serde_json::from_str(&item_ids_str).unwrap_or_default();
Ok(ContextPack {
id: row.get(0)?,
title: row.get(1)?,
description: row.get(2)?,
constraints: row.get(3)?,
questions: row.get(4)?,
item_ids,
export_format: row.get(6)?,
created_at: row.get(7)?,
updated_at: row.get(8)?,
})
}capture_item function · rust · L57-L92 (36 LOC)src-tauri/src/commands.rs
pub fn capture_item(
db: State<'_, Database>,
content: String,
source_app: String,
source_url: Option<String>,
source_title: Option<String>,
tags: Vec<String>,
) -> Result<CaptureItem, String> {
let conn = db.conn.lock().map_err(|e| e.to_string())?;
let id = Uuid::new_v4().to_string();
let now = Utc::now().to_rfc3339();
let char_count = content.len() as i64;
let tags_json = serde_json::to_string(&tags).unwrap_or_else(|_| "[]".to_string());
conn.execute(
"INSERT INTO items (id, content, content_type, source_app, source_url, source_title, tags, char_count, is_archived, created_at, updated_at)
VALUES (?1, ?2, 'text', ?3, ?4, ?5, ?6, ?7, 0, ?8, ?9)",
params![id, content, source_app, source_url, source_title, tags_json, char_count, now, now],
).map_err(|e| e.to_string())?;
for tag in &tags {
let color_index = tag_color_index(tag);
conn.execute(
"INSERT INTO tags (name, use_count, capture_screenshot function · rust · L95-L169 (75 LOC)src-tauri/src/commands.rs
pub fn capture_screenshot(
db: State<'_, Database>,
tags: Vec<String>,
) -> Result<CaptureItem, String> {
// Get data dir for storing images
let home = std::env::var("HOME").unwrap_or_else(|_| ".".to_string());
let images_dir = PathBuf::from(&home).join(".research-inbox").join("images");
std::fs::create_dir_all(&images_dir).map_err(|e| e.to_string())?;
let img_id = Uuid::new_v4().to_string();
let img_path = images_dir.join(format!("{}.png", img_id));
let img_path_str = img_path.to_string_lossy().to_string();
// Get foreground app BEFORE screencapture (which steals focus)
let app_info = crate::source_detect::get_foreground_app();
// Interactive screen region capture (macOS)
let status = Command::new("screencapture")
.args(["-i", &img_path_str])
.status()
.map_err(|e| e.to_string())?;
if !status.success() || !img_path.exists() {
return Err("Screenshot cancelled or failed".to_string());
}
check_duplicate function · rust · L172-L185 (14 LOC)src-tauri/src/commands.rs
pub fn check_duplicate(
db: State<'_, Database>,
content: String,
) -> Result<bool, String> {
let conn = db.conn.lock().map_err(|e| e.to_string())?;
// Check if identical content exists in last 100 items
let exists: bool = conn.query_row(
"SELECT COUNT(*) > 0 FROM (SELECT content FROM items WHERE is_archived = 0 ORDER BY created_at DESC LIMIT 100) WHERE content = ?1",
params![content],
|row| row.get(0),
).unwrap_or(false);
Ok(exists)
}Citation: Repobility (2026). State of AI-Generated Code. https://repobility.com/research/
get_ocr_binary_path function · rust · L186-L210 (25 LOC)src-tauri/src/commands.rs
fn get_ocr_binary_path() -> String {
let exe = std::env::current_exe().unwrap_or_default();
let exe_dir = exe.parent().unwrap_or(std::path::Path::new("."));
// macOS .app bundle: Contents/MacOS/../Resources/scripts/ocr
let resources = exe_dir.parent().unwrap_or(exe_dir).join("Resources").join("scripts").join("ocr");
if resources.exists() {
return resources.to_string_lossy().to_string();
}
// Next to binary
let beside_exe = exe_dir.join("ocr");
if beside_exe.exists() {
return beside_exe.to_string_lossy().to_string();
}
// Development: cargo manifest dir
let dev_path = PathBuf::from(env!("CARGO_MANIFEST_DIR")).join("scripts").join("ocr");
if dev_path.exists() {
return dev_path.to_string_lossy().to_string();
}
"ocr".to_string()
}list_items function · rust · L213-L245 (33 LOC)src-tauri/src/commands.rs
pub fn list_items(
db: State<'_, Database>,
offset: u32,
limit: u32,
archived: bool,
tag_filter: Option<String>,
source_filter: Option<String>,
) -> Result<Vec<CaptureItem>, String> {
let conn = db.conn.lock().map_err(|e| e.to_string())?;
let archived_val: i32 = if archived { 1 } else { 0 };
let mut sql = String::from(
"SELECT id, content, content_type, source_app, source_url, source_title, tags, char_count, is_archived, created_at, updated_at FROM items WHERE is_archived = ?"
);
let mut params_vec: Vec<Box<dyn rusqlite::types::ToSql>> = vec![Box::new(archived_val)];
if let Some(ref tag) = tag_filter {
sql.push_str(" AND tags LIKE ?");
params_vec.push(Box::new(format!("%\"{}\"%" , tag)));
}
if let Some(ref source) = source_filter {
sql.push_str(" AND LOWER(source_app) = LOWER(?)");
params_vec.push(Box::new(source.clone()));
}
sql.push_str(" ORDER BY created_at DESC LIMIT ? OFFSET ?search_items function · rust · L248-L307 (60 LOC)src-tauri/src/commands.rs
pub fn search_items(
db: State<'_, Database>,
query: String,
limit: u32,
) -> Result<Vec<CaptureItem>, String> {
let conn = db.conn.lock().map_err(|e| e.to_string())?;
if query.trim().is_empty() {
let mut stmt = conn.prepare(
"SELECT id, content, content_type, source_app, source_url, source_title, tags, char_count, is_archived, created_at, updated_at FROM items WHERE is_archived = 0 ORDER BY created_at DESC LIMIT ?1"
).map_err(|e| e.to_string())?;
let rows = stmt.query_map(params![limit], row_to_item).map_err(|e| e.to_string())?;
return Ok(rows.filter_map(|r| r.ok()).collect());
}
// Parse special filters
let mut fts_parts: Vec<String> = Vec::new();
let mut extra_where: Vec<String> = Vec::new();
for part in query.split_whitespace() {
if let Some(tag) = part.strip_prefix('#') {
extra_where.push(format!("i.tags LIKE '%\"{}\"'", tag.replace('\'', "''").to_lowercase()));
} elsupdate_item function · rust · L310-L348 (39 LOC)src-tauri/src/commands.rs
pub fn update_item(
db: State<'_, Database>,
id: String,
content: Option<String>,
tags: Option<Vec<String>>,
is_archived: Option<bool>,
) -> Result<CaptureItem, String> {
let conn = db.conn.lock().map_err(|e| e.to_string())?;
let now = Utc::now().to_rfc3339();
if let Some(ref c) = content {
conn.execute(
"UPDATE items SET content = ?1, char_count = ?2, updated_at = ?3 WHERE id = ?4",
params![c, c.len() as i64, now, id],
).map_err(|e| e.to_string())?;
}
if let Some(ref t) = tags {
let tags_json = serde_json::to_string(t).unwrap_or_else(|_| "[]".to_string());
conn.execute("UPDATE items SET tags = ?1, updated_at = ?2 WHERE id = ?3", params![tags_json, now, id])
.map_err(|e| e.to_string())?;
for tag in t {
let ci = tag_color_index(tag);
conn.execute(
"INSERT INTO tags (name, use_count, last_used_at, color_index) VALUES (?1, 1, ?2, ?3)
delete_item function · rust · L351-L355 (5 LOC)src-tauri/src/commands.rs
pub fn delete_item(db: State<'_, Database>, id: String) -> Result<(), String> {
let conn = db.conn.lock().map_err(|e| e.to_string())?;
conn.execute("DELETE FROM items WHERE id = ?1", params![id]).map_err(|e| e.to_string())?;
Ok(())
}list_tags function · rust · L360-L382 (23 LOC)src-tauri/src/commands.rs
pub fn list_tags(
db: State<'_, Database>,
prefix: Option<String>,
limit: u32,
) -> Result<Vec<Tag>, String> {
let conn = db.conn.lock().map_err(|e| e.to_string())?;
let items: Vec<Tag> = if let Some(ref p) = prefix {
let search = format!("{}%", p.to_lowercase());
let mut stmt = conn.prepare(
"SELECT name, use_count, last_used_at, color_index FROM tags WHERE name LIKE ?1 ORDER BY use_count DESC LIMIT ?2"
).map_err(|e| e.to_string())?;
let rows = stmt.query_map(params![search, limit], row_to_tag).map_err(|e| e.to_string())?;
rows.filter_map(|r| r.ok()).collect()
} else {
let mut stmt = conn.prepare(
"SELECT name, use_count, last_used_at, color_index FROM tags ORDER BY use_count DESC LIMIT ?1"
).map_err(|e| e.to_string())?;
let rows = stmt.query_map(params![limit], row_to_tag).map_err(|e| e.to_string())?;
rows.filter_map(|r| r.ok()).collect()
};
Ok(items)
}create_pack function · rust · L387-L411 (25 LOC)src-tauri/src/commands.rs
pub fn create_pack(
db: State<'_, Database>,
title: String,
description: Option<String>,
constraints: Option<String>,
questions: Option<String>,
item_ids: Vec<String>,
export_format: String,
) -> Result<ContextPack, String> {
let conn = db.conn.lock().map_err(|e| e.to_string())?;
let id = Uuid::new_v4().to_string();
let now = Utc::now().to_rfc3339();
let item_ids_json = serde_json::to_string(&item_ids).unwrap_or_else(|_| "[]".to_string());
conn.execute(
"INSERT INTO packs (id, title, description, constraints_text, questions, item_ids, export_format, created_at, updated_at)
VALUES (?1, ?2, ?3, ?4, ?5, ?6, ?7, ?8, ?9)",
params![id, title, description, constraints, questions, item_ids_json, export_format, now, now],
).map_err(|e| e.to_string())?;
Ok(ContextPack {
id, title, description, constraints, questions, item_ids, export_format,
created_at: now.clone(), updated_at: now,
})
}update_pack function · rust · L414-L451 (38 LOC)src-tauri/src/commands.rs
pub fn update_pack(
db: State<'_, Database>,
id: String,
title: Option<String>,
description: Option<String>,
constraints: Option<String>,
questions: Option<String>,
item_ids: Option<Vec<String>>,
export_format: Option<String>,
) -> Result<ContextPack, String> {
let conn = db.conn.lock().map_err(|e| e.to_string())?;
let now = Utc::now().to_rfc3339();
if let Some(ref t) = title {
conn.execute("UPDATE packs SET title = ?1, updated_at = ?2 WHERE id = ?3", params![t, now, id]).map_err(|e| e.to_string())?;
}
if let Some(ref d) = description {
conn.execute("UPDATE packs SET description = ?1, updated_at = ?2 WHERE id = ?3", params![d, now, id]).map_err(|e| e.to_string())?;
}
if let Some(ref c) = constraints {
conn.execute("UPDATE packs SET constraints_text = ?1, updated_at = ?2 WHERE id = ?3", params![c, now, id]).map_err(|e| e.to_string())?;
}
if let Some(ref q) = questions {
conn.execute("UPDRepobility · open methodology · https://repobility.com/research/
list_packs function · rust · L454-L461 (8 LOC)src-tauri/src/commands.rs
pub fn list_packs(db: State<'_, Database>, limit: u32) -> Result<Vec<ContextPack>, String> {
let conn = db.conn.lock().map_err(|e| e.to_string())?;
let mut stmt = conn.prepare(
"SELECT id, title, description, constraints_text, questions, item_ids, export_format, created_at, updated_at FROM packs ORDER BY updated_at DESC LIMIT ?1"
).map_err(|e| e.to_string())?;
let rows = stmt.query_map(params![limit], row_to_pack).map_err(|e| e.to_string())?;
Ok(rows.filter_map(|r| r.ok()).collect())
}export_pack function · rust · L464-L483 (20 LOC)src-tauri/src/commands.rs
pub fn export_pack(db: State<'_, Database>, id: String, format: String) -> Result<String, String> {
let conn = db.conn.lock().map_err(|e| e.to_string())?;
let mut stmt = conn.prepare(
"SELECT id, title, description, constraints_text, questions, item_ids, export_format, created_at, updated_at FROM packs WHERE id = ?1"
).map_err(|e| e.to_string())?;
let pack = stmt.query_row(params![id], row_to_pack).map_err(|e| e.to_string())?;
let mut items: Vec<CaptureItem> = Vec::new();
for item_id in &pack.item_ids {
let mut item_stmt = conn.prepare(
"SELECT id, content, content_type, source_app, source_url, source_title, tags, char_count, is_archived, created_at, updated_at FROM items WHERE id = ?1"
).map_err(|e| e.to_string())?;
if let Ok(item) = item_stmt.query_row(params![item_id], row_to_item) {
items.push(item);
}
}
Ok(format_pack(&pack, &items, &format))
}delete_pack function · rust · L486-L490 (5 LOC)src-tauri/src/commands.rs
pub fn delete_pack(db: State<'_, Database>, id: String) -> Result<(), String> {
let conn = db.conn.lock().map_err(|e| e.to_string())?;
conn.execute("DELETE FROM packs WHERE id = ?1", params![id]).map_err(|e| e.to_string())?;
Ok(())
}get_settings function · rust · L495-L518 (24 LOC)src-tauri/src/commands.rs
pub fn get_settings(db: State<'_, Database>) -> Result<AppSettings, String> {
let conn = db.conn.lock().map_err(|e| e.to_string())?;
let mut settings = AppSettings::default();
let mut stmt = conn.prepare("SELECT key, value FROM settings").map_err(|e| e.to_string())?;
let rows = stmt.query_map([], |row| {
Ok((row.get::<_, String>(0)?, row.get::<_, String>(1)?))
}).map_err(|e| e.to_string())?;
for row in rows.flatten() {
match row.0.as_str() {
"capture_hotkey" => settings.capture_hotkey = row.1,
"panel_hotkey" => settings.panel_hotkey = row.1,
"quick_tag_on_capture" => settings.quick_tag_on_capture = row.1 == "true",
"default_export_format" => settings.default_export_format = row.1,
"max_capture_size_kb" => settings.max_capture_size_kb = row.1.parse().unwrap_or(50),
"launch_at_login" => settings.launch_at_login = row.1 == "true",
"theme" => settings.theme = row.1,
update_settings function · rust · L521-L541 (21 LOC)src-tauri/src/commands.rs
pub fn update_settings(db: State<'_, Database>, settings: AppSettings) -> Result<(), String> {
let conn = db.conn.lock().map_err(|e| e.to_string())?;
let pairs = vec![
("capture_hotkey", settings.capture_hotkey),
("panel_hotkey", settings.panel_hotkey),
("quick_tag_on_capture", settings.quick_tag_on_capture.to_string()),
("default_export_format", settings.default_export_format),
("max_capture_size_kb", settings.max_capture_size_kb.to_string()),
("launch_at_login", settings.launch_at_login.to_string()),
("theme", settings.theme),
("language", settings.language),
("data_location", settings.data_location),
];
for (key, value) in pairs {
conn.execute(
"INSERT INTO settings (key, value) VALUES (?1, ?2) ON CONFLICT(key) DO UPDATE SET value = ?2",
params![key, value],
).map_err(|e| e.to_string())?;
}
Ok(())
}get_foreground_app_cmd function · rust · L546-L548 (3 LOC)src-tauri/src/commands.rs
pub fn get_foreground_app_cmd() -> Result<AppInfo, String> {
Ok(crate::source_detect::get_foreground_app())
}check_accessibility function · rust · L552-L567 (16 LOC)src-tauri/src/commands.rs
pub fn check_accessibility() -> bool {
#[cfg(target_os = "macos")]
{
use std::process::Command;
let output = Command::new("osascript")
.arg("-e")
.arg(r#"tell application "System Events" to keystroke ""#)
.output();
match output {
Ok(o) => !String::from_utf8_lossy(&o.stderr).contains("not allowed"),
Err(_) => false,
}
}
#[cfg(not(target_os = "macos"))]
{ true }
}refocus_app function · rust · L571-L581 (11 LOC)src-tauri/src/commands.rs
pub fn refocus_app(app_name: String) {
#[cfg(target_os = "macos")]
{
use std::process::Command;
let script = format!(
r#"tell application "{}" to activate"#,
app_name.replace('"', r#"\""#)
);
let _ = Command::new("osascript").arg("-e").arg(&script).spawn();
}
}Repobility · severity-and-effort ranking · https://repobility.com
open_input_monitoring_settings function · rust · L585-L593 (9 LOC)src-tauri/src/commands.rs
pub fn open_input_monitoring_settings() {
#[cfg(target_os = "macos")]
{
use std::process::Command;
let _ = Command::new("open")
.arg("x-apple.systempreferences:com.apple.preference.security?Privacy_ListenEvent")
.spawn();
}
}open_accessibility_settings function · rust · L597-L605 (9 LOC)src-tauri/src/commands.rs
pub fn open_accessibility_settings() {
#[cfg(target_os = "macos")]
{
use std::process::Command;
let _ = Command::new("open")
.arg("x-apple.systempreferences:com.apple.preference.security?Privacy_Accessibility")
.spawn();
}
}trigger_text_capture function · rust · L609-L614 (6 LOC)src-tauri/src/commands.rs
pub fn trigger_text_capture(app_handle: tauri::AppHandle) -> Result<(), String> {
let app_info = crate::source_detect::get_foreground_app();
let payload = serde_json::to_string(&app_info).unwrap_or_default();
let result = app_handle.emit("overlay-capture-text", payload).map_err(|e: tauri::Error| e.to_string());
result
}trigger_screenshot_capture function · rust · L618-L621 (4 LOC)src-tauri/src/commands.rs
pub fn trigger_screenshot_capture(app_handle: tauri::AppHandle) -> Result<(), String> {
let result = app_handle.emit("overlay-capture-screenshot", ()).map_err(|e: tauri::Error| e.to_string());
result
}tag_color_index function · rust · L624-L628 (5 LOC)src-tauri/src/commands.rs
fn tag_color_index(tag: &str) -> i64 {
let hash: u32 = tag.bytes().fold(0u32, |acc, b| acc.wrapping_mul(31).wrapping_add(b as u32));
(hash % 8) as i64
}fmt_time function · rust · L631-L642 (12 LOC)src-tauri/src/commands.rs
fn fmt_time(iso: &str) -> String {
let months = ["Jan","Feb","Mar","Apr","May","Jun","Jul","Aug","Sep","Oct","Nov","Dec"];
if iso.len() >= 16 {
let month_idx: usize = iso[5..7].parse().unwrap_or(1);
let day: &str = &iso[8..10];
let time: &str = &iso[11..16];
let month = months.get(month_idx.wrapping_sub(1)).unwrap_or(&"???");
format!("{} {}, {}", month, day.trim_start_matches('0'), time)
} else {
iso.to_string()
}
}fmt_source function · rust · L645-L650 (6 LOC)src-tauri/src/commands.rs
fn fmt_source(app: &str, url: Option<&str>, title: Option<&str>) -> String {
let mut parts = vec![app.to_string()];
if let Some(u) = url { if !u.is_empty() { parts.push(u.to_string()); } }
if let Some(t) = title { if !t.is_empty() { parts.push(t.to_string()); } }
parts.join(" | ")
}format_pack function · rust · L651-L718 (68 LOC)src-tauri/src/commands.rs
pub fn format_pack(pack: &ContextPack, items: &[CaptureItem], format: &str) -> String {
let title = if pack.title.is_empty() { "Context Pack" } else { &pack.title };
let desc = pack.description.as_deref().unwrap_or("");
let constraints = pack.constraints.as_deref().unwrap_or("");
let questions = pack.questions.as_deref().unwrap_or("");
let date = if pack.created_at.len() >= 10 { &pack.created_at[..10] } else { &pack.created_at };
match format {
"claude" => {
let mut out = String::from("<context>\n");
if !title.is_empty() { out.push_str(&format!("<title>{}</title>\n", title)); }
out.push_str(&format!("<summary>{}</summary>\n\n<evidence count=\"{}\">\n", desc, items.len()));
for item in items {
let mut attrs = format!("source=\"{}\" date=\"{}\"", item.source_app, fmt_time(&item.created_at));
if let Some(ref u) = item.source_url { if !u.is_empty() { attrs.push_str(&format!(" uGenerated by Repobility's multi-pass static-analysis pipeline (https://repobility.com)
test_fmt_time function · rust · L725-L729 (5 LOC)src-tauri/src/commands.rs
fn test_fmt_time() {
assert_eq!(fmt_time("2026-03-28T12:44:30.973176+00:00"), "Mar 28, 12:44");
assert_eq!(fmt_time("2026-01-05T09:01:00Z"), "Jan 5, 09:01");
assert_eq!(fmt_time("short"), "short");
}test_fmt_source_full function · rust · L732-L735 (4 LOC)src-tauri/src/commands.rs
fn test_fmt_source_full() {
let s = fmt_source("Chrome", Some("https://example.com"), Some("My Page"));
assert_eq!(s, "Chrome | https://example.com | My Page");
}test_fmt_source_no_url function · rust · L738-L741 (4 LOC)src-tauri/src/commands.rs
fn test_fmt_source_no_url() {
let s = fmt_source("Telegram", None, Some("Chat with Bob"));
assert_eq!(s, "Telegram | Chat with Bob");
}page 1 / 2next ›