gitkraft_gui/features/staging/
update.rs1use iced::Task;
4
5use crate::message::Message;
6use crate::state::GitKraft;
7
8use super::commands;
9
10pub fn update(state: &mut GitKraft, message: Message) -> Task<Message> {
13 match message {
14 Message::StageFile(path) => {
15 state.active_tab_mut().context_menu = None;
16 with_repo!(state, format!("Staging '{path}'…"), |repo_path| {
17 commands::stage_file(repo_path, path)
18 })
19 }
20
21 Message::UnstageFile(path) => {
22 state.active_tab_mut().context_menu = None;
23 with_repo!(state, format!("Unstaging '{path}'…"), |repo_path| {
24 commands::unstage_file(repo_path, path)
25 })
26 }
27
28 Message::StageAll => {
29 state.active_tab_mut().context_menu = None;
30 with_repo!(state, "Staging all files…".into(), |repo_path| {
31 commands::stage_all(repo_path)
32 })
33 }
34
35 Message::UnstageAll => {
36 state.active_tab_mut().context_menu = None;
37 with_repo!(state, "Unstaging all files…".into(), |repo_path| {
38 commands::unstage_all(repo_path)
39 })
40 }
41
42 Message::DiscardFile(path) => {
43 state.active_tab_mut().context_menu = None;
44 state.active_tab_mut().pending_discard = None;
45 with_repo!(state, format!("Discarding '{path}'…"), |repo_path| {
46 commands::discard_file(repo_path, path)
47 })
48 }
49
50 Message::ConfirmDiscard(path) => {
51 with_repo!(
52 state,
53 format!("Discarding changes in '{path}'…"),
54 |repo_path| {
55 state.active_tab_mut().pending_discard = None;
56 commands::discard_file(repo_path, path)
57 }
58 )
59 }
60
61 Message::CancelDiscard => {
62 let tab = state.active_tab_mut();
63 tab.pending_discard = None;
64 tab.status_message = None;
65 Task::none()
66 }
67
68 Message::StagingUpdated(result) => {
69 let tab = state.active_tab_mut();
70 match result {
71 Ok(payload) => {
72 tab.unstaged_changes = payload.unstaged;
73 tab.staged_changes = payload.staged;
74 tab.status_message = Some("Staging area updated.".into());
75 }
76 Err(e) => {
77 tab.error_message = Some(format!("Staging operation failed: {e}"));
78 tab.status_message = None;
79 }
80 }
81 Task::none()
82 }
83
84 Message::ToggleSelectUnstaged(path) => {
85 let tab = state.active_tab_mut();
86 if tab.selected_unstaged.contains(&path) {
87 tab.selected_unstaged.remove(&path);
88 } else {
89 tab.selected_unstaged.insert(path);
90 }
91 Task::none()
92 }
93
94 Message::ToggleSelectStaged(path) => {
95 let tab = state.active_tab_mut();
96 if tab.selected_staged.contains(&path) {
97 tab.selected_staged.remove(&path);
98 } else {
99 tab.selected_staged.insert(path);
100 }
101 Task::none()
102 }
103
104 Message::StageSelected => {
105 let paths: Vec<String> = state
106 .active_tab()
107 .selected_unstaged
108 .iter()
109 .cloned()
110 .collect();
111 if paths.is_empty() {
112 return Task::none();
113 }
114 state.active_tab_mut().selected_unstaged.clear();
115 state.active_tab_mut().context_menu = None;
116 with_repo!(
117 state,
118 format!("Staging {} file(s)…", paths.len()),
119 |repo_path| commands::stage_files(repo_path, paths)
120 )
121 }
122
123 Message::UnstageSelected => {
124 let paths: Vec<String> = state.active_tab().selected_staged.iter().cloned().collect();
125 if paths.is_empty() {
126 return Task::none();
127 }
128 state.active_tab_mut().selected_staged.clear();
129 state.active_tab_mut().context_menu = None;
130 with_repo!(
131 state,
132 format!("Unstaging {} file(s)…", paths.len()),
133 |repo_path| commands::unstage_files(repo_path, paths)
134 )
135 }
136
137 Message::DiscardSelected => {
138 let unstaged_paths: Vec<String> = state
139 .active_tab()
140 .selected_unstaged
141 .iter()
142 .cloned()
143 .collect();
144 let staged_paths: Vec<String> =
145 state.active_tab().selected_staged.iter().cloned().collect();
146
147 if unstaged_paths.is_empty() && staged_paths.is_empty() {
148 return Task::none();
149 }
150
151 let total = unstaged_paths.len() + staged_paths.len();
152 state.active_tab_mut().selected_unstaged.clear();
153 state.active_tab_mut().selected_staged.clear();
154 state.active_tab_mut().context_menu = None;
155 with_repo!(
156 state,
157 format!("Discarding {} file(s)…", total),
158 |repo_path| commands::discard_all_selected(repo_path, unstaged_paths, staged_paths)
159 )
160 }
161
162 Message::DiscardStagedFile(path) => {
163 state.active_tab_mut().context_menu = None;
164 with_repo!(state, format!("Discarding '{path}'…"), |repo_path| {
165 commands::discard_staged_file(repo_path, path)
166 })
167 }
168
169 _ => Task::none(),
170 }
171}