gitkraft_gui/features/diff/
update.rs1use iced::Task;
4
5use crate::message::Message;
6use crate::state::GitKraft;
7
8pub fn update(state: &mut GitKraft, message: Message) -> Task<Message> {
11 match message {
12 Message::SelectDiffByIndex(index) => {
13 let shift_held = state.keyboard_modifiers.shift();
14 let tab = state.active_tab();
15 let repo_path = tab.repo_path.clone();
16 let oid = tab.selected_commit_oid.clone();
17
18 if shift_held {
19 let anchor = state
26 .active_tab()
27 .anchor_file_index
28 .or(state.active_tab().selected_file_index)
29 .unwrap_or(index);
30
31 let (start, end) = if anchor <= index {
32 (anchor, index)
33 } else {
34 (index, anchor)
35 };
36
37 let range: Vec<usize> = (start..=end).collect();
40 let count = range.len();
41
42 let tab = state.active_tab_mut();
43 tab.selected_commit_file_indices = range;
44 tab.selected_file_index = Some(index);
45
46 if count == 1 {
47 tab.multi_file_diffs.clear();
50 let file_entry = tab.commit_files.get(start).cloned();
51 if let (Some(entry), Some(path), Some(oid)) = (file_entry, repo_path, oid) {
52 let file_path = entry.display_path().to_string();
53 let tab = state.active_tab_mut();
54 tab.is_loading_file_diff = true;
55 tab.diff_scroll_offset = 0.0;
56 return crate::features::commits::commands::load_single_file_diff(
57 path, oid, file_path,
58 );
59 }
60 } else {
61 tab.selected_diff = None;
63 tab.is_loading_file_diff = true;
64 tab.diff_scroll_offset = 0.0;
65 let file_paths: Vec<String> = tab
66 .selected_commit_file_indices
67 .iter()
68 .filter_map(|&i| {
69 tab.commit_files
70 .get(i)
71 .map(|f| f.display_path().to_string())
72 })
73 .collect();
74 if let (Some(path), Some(oid)) = (repo_path, oid) {
75 return crate::features::commits::commands::load_commit_multi_diffs(
76 path, oid, file_paths,
77 );
78 }
79 }
80 Task::none()
81 } else {
82 let tab = state.active_tab_mut();
84 tab.anchor_file_index = Some(index); tab.selected_commit_file_indices.clear();
86 tab.multi_file_diffs.clear();
87 tab.commit_range_diffs.clear();
88
89 let file_entry = tab.commit_files.get(index).cloned();
90 if let (Some(entry), Some(path), Some(oid)) = (file_entry, repo_path, oid) {
91 let file_path = entry.display_path().to_string();
92 let tab = state.active_tab_mut();
93 tab.selected_file_index = Some(index);
94 tab.is_loading_file_diff = true;
95 tab.diff_scroll_offset = 0.0;
96 crate::features::commits::commands::load_single_file_diff(path, oid, file_path)
97 } else {
98 Task::none()
99 }
100 }
101 }
102
103 Message::SelectDiff(diff_info) => {
104 state.active_tab_mut().context_menu = None;
105 let tab = state.active_tab_mut();
106 tab.selected_diff = Some(diff_info);
107 tab.diff_scroll_offset = 0.0;
108 Task::none()
109 }
110
111 Message::CommitMultiDiffLoaded(result) => {
112 let tab = state.active_tab_mut();
113 tab.is_loading_file_diff = false;
114 match result {
115 Ok(diffs) => {
116 tab.multi_file_diffs = diffs;
117 tab.selected_diff = None;
118 tab.diff_scroll_offset = 0.0;
119 }
120 Err(e) => {
121 tab.multi_file_diffs.clear();
122 tab.error_message = Some(format!("Failed to load multi-file diff: {e}"));
123 }
124 }
125 Task::none()
126 }
127
128 _ => Task::none(),
129 }
130}