super-stt-app/src/core/app/handlers/models_page/install.rs
Line | Count | Source |
1 | | // SPDX-License-Identifier: GPL-3.0-only |
2 | | |
3 | | use crate::core::app::AppModel; |
4 | | use crate::ui::messages::{BackendMessage, Message, ModelsPageMessage}; |
5 | | use cosmic::prelude::*; |
6 | | |
7 | | impl AppModel { |
8 | 0 | pub(in crate::core::app) fn handle_models_install_lifecycle( |
9 | 0 | &mut self, |
10 | 0 | message: ModelsPageMessage, |
11 | 0 | ) -> Task<cosmic::Action<Message>> { |
12 | 0 | match message { |
13 | | // Registry / Download-tab messages |
14 | 0 | ModelsPageMessage::InstallBackend(source) => { |
15 | | // Clear a prior "failed to start" so the card reads "Installing…". |
16 | 0 | self.registry.install_errors.remove(&source); |
17 | 0 | let s = source.clone(); |
18 | 0 | Task::perform( |
19 | 0 | async move { crate::daemon::registry::install_by_source(&s).await }, |
20 | 0 | move |res| { |
21 | 0 | cosmic::Action::App(Message::ModelsPage(match res { |
22 | 0 | Ok(a) => ModelsPageMessage::InstallAccepted { |
23 | 0 | source: source.clone(), |
24 | 0 | install_id: a.install_id, |
25 | 0 | }, |
26 | 0 | Err(e) => ModelsPageMessage::InstallFailedToStart { |
27 | 0 | source: source.clone(), |
28 | 0 | error: e.to_string(), |
29 | 0 | }, |
30 | | })) |
31 | 0 | }, |
32 | | ) |
33 | | } |
34 | | |
35 | 0 | ModelsPageMessage::InstallBackendFromRepoUrl(url) => { |
36 | 0 | self.registry.install_errors.remove(&url); |
37 | 0 | let u = url.clone(); |
38 | 0 | Task::perform( |
39 | 0 | async move { crate::daemon::registry::install_by_repo_url(&u).await }, |
40 | 0 | move |res| { |
41 | 0 | cosmic::Action::App(Message::ModelsPage(match res { |
42 | 0 | Ok(a) => ModelsPageMessage::InstallAccepted { |
43 | 0 | source: url.clone(), |
44 | 0 | install_id: a.install_id, |
45 | 0 | }, |
46 | 0 | Err(e) => ModelsPageMessage::InstallFailedToStart { |
47 | 0 | source: url.clone(), |
48 | 0 | error: e.to_string(), |
49 | 0 | }, |
50 | | })) |
51 | 0 | }, |
52 | | ) |
53 | | } |
54 | | |
55 | 0 | ModelsPageMessage::InstallAccepted { source, install_id } => { |
56 | | use crate::state::registry::InstallStatus; |
57 | | use super_stt_shared::registry::events::InstallPhase; |
58 | | // The request was accepted — retire any prior start error. |
59 | 0 | self.registry.install_errors.remove(&source); |
60 | 0 | self.registry.installs.insert( |
61 | 0 | source, |
62 | 0 | InstallStatus { |
63 | 0 | install_id, |
64 | 0 | phase: InstallPhase::Downloading, |
65 | 0 | bytes_done: 0, |
66 | 0 | bytes_total: None, |
67 | 0 | error: None, |
68 | 0 | }, |
69 | | ); |
70 | 0 | Task::none() |
71 | | } |
72 | | |
73 | 0 | ModelsPageMessage::InstallFailedToStart { source, error } => { |
74 | 0 | log::error!("install({source}) failed to start: {error}"); |
75 | | // Drop the pending marker (there is no background install) and |
76 | | // record the reason so the Browse card shows "Failed" + a note |
77 | | // instead of silently snapping back to the Install button. |
78 | 0 | self.registry.installs.remove(&source); |
79 | 0 | self.registry.install_errors.insert(source, error); |
80 | 0 | Task::none() |
81 | | } |
82 | | |
83 | 0 | ModelsPageMessage::UpdateBackend(source) => { |
84 | 0 | self.registry.install_errors.remove(&source); |
85 | 0 | let s = source.clone(); |
86 | 0 | Task::perform( |
87 | 0 | async move { crate::daemon::registry::update(&s).await }, |
88 | 0 | move |res| { |
89 | 0 | cosmic::Action::App(match res { |
90 | 0 | Ok(r) if r.noop => { |
91 | 0 | log::info!("update({source}) noop — already at {}", r.to_version); |
92 | | // Nothing to do; let the UI settle naturally. |
93 | 0 | Message::Backend(BackendMessage::BackendsReload) |
94 | | } |
95 | 0 | Ok(r) => Message::ModelsPage(ModelsPageMessage::InstallAccepted { |
96 | 0 | source: source.clone(), |
97 | 0 | install_id: r.install_id.unwrap_or_default(), |
98 | 0 | }), |
99 | 0 | Err(e) => { |
100 | 0 | Message::ModelsPage(ModelsPageMessage::InstallFailedToStart { |
101 | 0 | source: source.clone(), |
102 | 0 | error: e.to_string(), |
103 | 0 | }) |
104 | | } |
105 | | }) |
106 | 0 | }, |
107 | | ) |
108 | | } |
109 | | |
110 | 0 | _ => Task::none(), |
111 | | } |
112 | 0 | } |
113 | | |
114 | | /// Uninstall lifecycle: kick off the request and surface its failure. |
115 | 0 | pub(in crate::core::app) fn handle_models_uninstall( |
116 | 0 | &mut self, |
117 | 0 | message: ModelsPageMessage, |
118 | 0 | ) -> Task<cosmic::Action<Message>> { |
119 | 0 | match message { |
120 | 0 | ModelsPageMessage::UninstallBackend(source) => { |
121 | | // Clear any stale failure so the row reads "in progress" on retry. |
122 | 0 | self.registry.uninstall_errors.remove(&source); |
123 | 0 | let s = source.clone(); |
124 | 0 | Task::perform( |
125 | 0 | async move { crate::daemon::registry::uninstall(&s).await }, |
126 | 0 | move |res| { |
127 | 0 | cosmic::Action::App(match res { |
128 | 0 | Ok(_) => Message::Backend(BackendMessage::BackendsReload), |
129 | 0 | Err(error) => Message::ModelsPage(ModelsPageMessage::UninstallFailed { |
130 | 0 | source: source.clone(), |
131 | 0 | error: error.to_string(), |
132 | 0 | }), |
133 | | }) |
134 | 0 | }, |
135 | | ) |
136 | | } |
137 | | |
138 | 0 | ModelsPageMessage::UninstallFailed { source, error } => { |
139 | 0 | log::error!("uninstall({source}) failed: {error}"); |
140 | 0 | self.registry.uninstall_errors.insert(source, error); |
141 | 0 | Task::none() |
142 | | } |
143 | | |
144 | 0 | _ => Task::none(), |
145 | | } |
146 | 0 | } |
147 | | |
148 | 0 | pub(in crate::core::app) fn handle_models_install_progress( |
149 | 0 | &mut self, |
150 | 0 | message: ModelsPageMessage, |
151 | 0 | ) -> Task<cosmic::Action<Message>> { |
152 | 0 | match message { |
153 | | ModelsPageMessage::InstallProgress { |
154 | 0 | install_id, |
155 | 0 | source, |
156 | 0 | phase, |
157 | 0 | bytes_done, |
158 | 0 | bytes_total, |
159 | | } => { |
160 | 0 | if let Some(s) = self.registry.installs.get_mut(&source) |
161 | 0 | && s.install_id == install_id |
162 | | { |
163 | 0 | s.phase = phase; |
164 | 0 | if let Some(d) = bytes_done { |
165 | 0 | s.bytes_done = d; |
166 | 0 | } |
167 | 0 | if let Some(t) = bytes_total { |
168 | 0 | s.bytes_total = Some(t); |
169 | 0 | } |
170 | 0 | } |
171 | 0 | Task::none() |
172 | | } |
173 | | |
174 | 0 | ModelsPageMessage::InstallCompleted { source } => { |
175 | 0 | self.registry.installs.remove(&source); |
176 | 0 | self.registry.install_errors.remove(&source); |
177 | | // Refresh the installed-backends list so the new install |
178 | | // shows up in the Installed tab. |
179 | 0 | crate::core::app::handlers::tasks::reload_backends() |
180 | | } |
181 | | |
182 | | ModelsPageMessage::InstallFailed { |
183 | 0 | install_id, |
184 | 0 | source, |
185 | 0 | phase, |
186 | 0 | error, |
187 | | } => { |
188 | 0 | if let Some(s) = self.registry.installs.get_mut(&source) |
189 | 0 | && s.install_id == install_id |
190 | 0 | { |
191 | 0 | s.error = Some(error); |
192 | 0 | s.phase = phase; |
193 | 0 | } |
194 | 0 | Task::none() |
195 | | } |
196 | | |
197 | 0 | _ => Task::none(), |
198 | | } |
199 | 0 | } |
200 | | } |