notedeck

One damus client to rule them all
git clone git://jb55.com/notedeck
Log | Files | Refs | README | LICENSE

diff.rs (3420B)


      1 use super::super::file_update::{DiffLine, DiffTag, FileUpdate, FileUpdateType};
      2 use egui::{Color32, RichText, Ui};
      3 
      4 /// Colors for diff rendering
      5 const DELETE_COLOR: Color32 = Color32::from_rgb(200, 60, 60);
      6 const INSERT_COLOR: Color32 = Color32::from_rgb(60, 180, 60);
      7 const LINE_NUMBER_COLOR: Color32 = Color32::from_rgb(128, 128, 128);
      8 
      9 /// Render a file update diff view
     10 pub fn file_update_ui(update: &FileUpdate, ui: &mut Ui) {
     11     // Code block frame - no scroll, just show full diff height
     12     egui::Frame::new()
     13         .fill(ui.visuals().extreme_bg_color)
     14         .inner_margin(8.0)
     15         .corner_radius(4.0)
     16         .show(ui, |ui| {
     17             render_diff_lines(update.diff_lines(), &update.update_type, ui);
     18         });
     19 }
     20 
     21 /// Render the diff lines with proper coloring
     22 fn render_diff_lines(lines: &[DiffLine], update_type: &FileUpdateType, ui: &mut Ui) {
     23     // Track line numbers for old and new
     24     let mut old_line = 1usize;
     25     let mut new_line = 1usize;
     26 
     27     for diff_line in lines {
     28         ui.horizontal(|ui| {
     29             // Line number gutter
     30             let (old_num, new_num) = match diff_line.tag {
     31                 DiffTag::Equal => {
     32                     let result = (Some(old_line), Some(new_line));
     33                     old_line += 1;
     34                     new_line += 1;
     35                     result
     36                 }
     37                 DiffTag::Delete => {
     38                     let result = (Some(old_line), None);
     39                     old_line += 1;
     40                     result
     41                 }
     42                 DiffTag::Insert => {
     43                     let result = (None, Some(new_line));
     44                     new_line += 1;
     45                     result
     46                 }
     47             };
     48 
     49             // Render line numbers (only for edits, not writes)
     50             if matches!(update_type, FileUpdateType::Edit { .. }) {
     51                 let old_str = old_num
     52                     .map(|n| format!("{:4}", n))
     53                     .unwrap_or_else(|| "    ".to_string());
     54                 let new_str = new_num
     55                     .map(|n| format!("{:4}", n))
     56                     .unwrap_or_else(|| "    ".to_string());
     57 
     58                 ui.label(
     59                     RichText::new(format!("{} {}", old_str, new_str))
     60                         .monospace()
     61                         .size(11.0)
     62                         .color(LINE_NUMBER_COLOR),
     63                 );
     64             }
     65 
     66             // Render the prefix and content
     67             let (prefix, color) = match diff_line.tag {
     68                 DiffTag::Equal => (" ", ui.visuals().text_color()),
     69                 DiffTag::Delete => ("-", DELETE_COLOR),
     70                 DiffTag::Insert => ("+", INSERT_COLOR),
     71             };
     72 
     73             // Remove trailing newline for display
     74             let content = diff_line.content.trim_end_matches('\n');
     75 
     76             ui.label(
     77                 RichText::new(format!("{} {}", prefix, content))
     78                     .monospace()
     79                     .size(12.0)
     80                     .color(color),
     81             );
     82         });
     83     }
     84 }
     85 
     86 /// Render the file path header (call within a horizontal layout)
     87 pub fn file_path_header(update: &FileUpdate, ui: &mut Ui) {
     88     let type_label = match &update.update_type {
     89         FileUpdateType::Edit { .. } => "Edit",
     90         FileUpdateType::Write { .. } => "Write",
     91     };
     92 
     93     ui.label(RichText::new(type_label).strong());
     94     ui.label(RichText::new(&update.file_path).monospace());
     95 }