Skip to content

Commit bf9c054

Browse files
feat: full-width review view with inline code viewer
- View mode hides left sidebar, shows full-width results - Click a finding to load code around that line (15-line context) - Code viewer with line numbers, amber highlight on target line - Findings list + code viewer in 40/60 split - Back button returns to create mode - Rust: new read_file_around_line command for targeted file reads Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
1 parent 3206870 commit bf9c054

4 files changed

Lines changed: 346 additions & 98 deletions

File tree

apps/desktop/src-tauri/src/commands/files.rs

Lines changed: 51 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -78,6 +78,57 @@ pub async fn read_file_preview(
7878
}))
7979
}
8080

81+
/// Read lines around a specific line number in a file.
82+
/// Returns context_before lines before and context_after lines after the target line.
83+
#[tauri::command]
84+
pub async fn read_file_around_line(
85+
file_path: String,
86+
line: u32,
87+
context_before: Option<u32>,
88+
context_after: Option<u32>,
89+
) -> Result<Value, String> {
90+
let path = Path::new(&file_path);
91+
if !path.is_file() {
92+
return Err(format!("Not a file: {file_path}"));
93+
}
94+
95+
let before = context_before.unwrap_or(10) as usize;
96+
let after = context_after.unwrap_or(10) as usize;
97+
let target = line as usize;
98+
let start = if target > before { target - before } else { 1 };
99+
let end = target + after;
100+
101+
let file = fs::File::open(path).map_err(|e| format!("Cannot open file: {e}"))?;
102+
let reader = BufReader::new(file);
103+
104+
let mut lines: Vec<Value> = Vec::new();
105+
for (i, result) in reader.lines().enumerate() {
106+
let line_num = i + 1;
107+
if line_num > end {
108+
break;
109+
}
110+
if line_num >= start {
111+
match result {
112+
Ok(text) => lines.push(json!({
113+
"line": line_num,
114+
"text": text,
115+
"highlight": line_num == target,
116+
})),
117+
Err(_) => break,
118+
}
119+
}
120+
}
121+
122+
let language = detect_language(path);
123+
124+
Ok(json!({
125+
"lines": lines,
126+
"language": language,
127+
"target_line": target,
128+
"file_path": file_path,
129+
}))
130+
}
131+
81132
/// Open a path in an external application (Cursor, VS Code, Finder, Terminal).
82133
#[tauri::command]
83134
pub async fn open_in_app(app_name: String, path: String) -> Result<Value, String> {

apps/desktop/src-tauri/src/main.rs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -243,6 +243,7 @@ fn main() {
243243
// File Tree
244244
commands::files::list_directory_tree,
245245
commands::files::read_file_preview,
246+
commands::files::read_file_around_line,
246247
commands::files::open_in_app,
247248
// Diff Comments
248249
commands::diff_comments::get_file_diff,

apps/desktop/src/lib/tauri-ipc.ts

Lines changed: 27 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1338,6 +1338,33 @@ export async function readFilePreview(
13381338
});
13391339
}
13401340

1341+
export interface FileLineData {
1342+
line: number;
1343+
text: string;
1344+
highlight: boolean;
1345+
}
1346+
1347+
export interface FileAroundLineResult {
1348+
lines: FileLineData[];
1349+
language: string;
1350+
target_line: number;
1351+
file_path: string;
1352+
}
1353+
1354+
export async function readFileAroundLine(
1355+
filePath: string,
1356+
line: number,
1357+
contextBefore?: number,
1358+
contextAfter?: number,
1359+
): Promise<FileAroundLineResult> {
1360+
return safeInvoke("read_file_around_line", {
1361+
filePath,
1362+
line,
1363+
contextBefore: contextBefore ?? 10,
1364+
contextAfter: contextAfter ?? 10,
1365+
});
1366+
}
1367+
13411368
export async function openInApp(
13421369
appName: string,
13431370
path: string

0 commit comments

Comments
 (0)