feat(downloads): Download cancelling

Signed-off-by: quexeky <git@quexeky.dev>
This commit is contained in:
quexeky
2024-11-21 16:46:05 +11:00
parent 18b914918c
commit 450bca9c5b
6 changed files with 44 additions and 12 deletions

View File

@ -9,7 +9,12 @@
Download game Download game
<span v-if="progress != 0"> ({{ Math.floor(progress * 1000) / 10 }}%) </span> <span v-if="progress != 0"> ({{ Math.floor(progress * 1000) / 10 }}%) </span>
</button> </button>
</template> <button
class="w-full rounded-md p-4 bg-blue-600 text-white"
@click="stopGameDownload"
>
Cancel game download
</button></template>
<script setup lang="ts"> <script setup lang="ts">
import { invoke } from "@tauri-apps/api/core"; import { invoke } from "@tauri-apps/api/core";
@ -36,4 +41,7 @@ async function startGameDownload() {
})(); })();
}, 100); }, 100);
} }
async function stopGameDownload() {
await invoke("stop_game_download", { "gameId": gameId.value })
}
</script> </script>

View File

@ -3,7 +3,7 @@ use crate::db::DatabaseImpls;
use crate::downloads::manifest::{DropDownloadContext, DropManifest}; use crate::downloads::manifest::{DropDownloadContext, DropManifest};
use crate::remote::RemoteAccessError; use crate::remote::RemoteAccessError;
use crate::DB; use crate::DB;
use log::info; use log::{debug, error, info};
use rayon::ThreadPoolBuilder; use rayon::ThreadPoolBuilder;
use std::fmt::{Display, Formatter}; use std::fmt::{Display, Formatter};
use std::fs::{create_dir_all, File}; use std::fs::{create_dir_all, File};
@ -239,7 +239,7 @@ impl GameDownloadAgent {
} }
}, },
Err(e) => { Err(e) => {
info!("GameDownloadError: {}", e); error!("GameDownloadError: {}", e);
self.sender.send(DownloadManagerSignal::Error(e)).unwrap(); self.sender.send(DownloadManagerSignal::Error(e)).unwrap();
new_contexts_ref.lock().unwrap().push(context); new_contexts_ref.lock().unwrap().push(context);
}, },
@ -247,11 +247,10 @@ impl GameDownloadAgent {
}); });
} }
}); });
info!("Acquiring lock");
if !new_contexts.lock().unwrap().is_empty() { if !new_contexts.lock().unwrap().is_empty() {
info!("New contexts not empty"); debug!("New contexts not empty");
*self.contexts.lock().unwrap() = Arc::into_inner(new_contexts).unwrap().into_inner().unwrap(); *self.contexts.lock().unwrap() = Arc::into_inner(new_contexts).unwrap().into_inner().unwrap();
info!("Contexts: {:?}", *self.contexts.lock().unwrap()); debug!("Contexts: {:?}", *self.contexts.lock().unwrap());
return Err(()) return Err(())
} }
info!("Contexts: {:?}", *self.contexts.lock().unwrap()); info!("Contexts: {:?}", *self.contexts.lock().unwrap());

View File

@ -1,5 +1,7 @@
use std::sync::Mutex; use std::sync::Mutex;
use log::info;
use crate::{AppError, AppState}; use crate::{AppError, AppState};
#[tauri::command] #[tauri::command]
@ -37,6 +39,7 @@ pub fn stop_game_download(
state: tauri::State<'_, Mutex<AppState>>, state: tauri::State<'_, Mutex<AppState>>,
game_id: String game_id: String
) { ) {
info!("Cancelling game download {}", game_id);
state state
.lock() .lock()
.unwrap() .unwrap()

View File

@ -7,7 +7,7 @@ use std::{
thread::spawn, thread::spawn,
}; };
use log::info; use log::{info, warn};
use super::{ use super::{
download_agent::{GameDownloadAgent, GameDownloadError}, download_agent::{GameDownloadAgent, GameDownloadError},
@ -78,6 +78,7 @@ pub enum DownloadManagerSignal {
/// Tells the Manager to stop the current /// Tells the Manager to stop the current
/// download and return /// download and return
Finish, Finish,
Cancel(String),
/// Any error which occurs in the agent /// Any error which occurs in the agent
Error(GameDownloadError), Error(GameDownloadError),
} }
@ -146,6 +147,9 @@ impl DownloadManagerBuilder {
DownloadManagerSignal::Error(e) => { DownloadManagerSignal::Error(e) => {
self.manage_error_signal(e); self.manage_error_signal(e);
}, },
DownloadManagerSignal::Cancel(id) => {
self.manage_cancel_signal(id);
},
}; };
} }
} }
@ -220,10 +224,11 @@ impl DownloadManagerBuilder {
spawn(move || { spawn(move || {
match download_agent.download() { match download_agent.download() {
Ok(_) => { Ok(_) => {
sender.send(DownloadManagerSignal::Completed(download_agent.id.clone())); sender.send(DownloadManagerSignal::Completed(download_agent.id.clone())).unwrap();
}, },
Err(_) => { Err(e) => {
todo!() // Account for if the setup_download function fails warn!("Download failed");
//todo!() // Account for if the setup_download function fails
}, },
}; };
}); });
@ -244,6 +249,22 @@ impl DownloadManagerBuilder {
*lock = GameDownloadStatus::Error; *lock = GameDownloadStatus::Error;
self.set_status(DownloadManagerStatus::Error); self.set_status(DownloadManagerStatus::Error);
} }
fn manage_cancel_signal(&mut self, game_id: String) {
if let Some(current_flag) = &self.active_control_flag {
current_flag.set(DownloadThreadControlFlag::Stop);
self.active_control_flag = None;
*self.progress.lock().unwrap() = None;
}
self.download_agent_registry.remove(&game_id);
let mut lock = self.download_queue.lock().unwrap();
let index = match lock.iter().position(|interface| interface.id == game_id) {
Some(index) => index,
None => return,
};
lock.remove(index);
self.sender.send(DownloadManagerSignal::Go).unwrap();
info!("{:?}", self.download_agent_registry.iter().map(|x| x.0.clone()).collect::<String>());
}
fn set_status(&self, status: DownloadManagerStatus) { fn set_status(&self, status: DownloadManagerStatus) {
*self.status.lock().unwrap() = status; *self.status.lock().unwrap() = status;
} }

View File

@ -76,9 +76,9 @@ impl DownloadManager {
} }
pub fn cancel_download( pub fn cancel_download(
&self, &self,
id: String game_id: String
) { ) {
todo!() self.command_sender.send(DownloadManagerSignal::Cancel(game_id)).unwrap();
} }
pub fn edit(&self) -> MutexGuard<'_, VecDeque<Arc<AgentInterfaceData>>> { pub fn edit(&self) -> MutexGuard<'_, VecDeque<Arc<AgentInterfaceData>>> {
self.download_queue.lock().unwrap() self.download_queue.lock().unwrap()

View File

@ -132,6 +132,7 @@ pub fn run() {
// Downloads // Downloads
download_game, download_game,
get_current_game_download_progress, get_current_game_download_progress,
stop_game_download
]) ])
.plugin(tauri_plugin_shell::init()) .plugin(tauri_plugin_shell::init())
.setup(|app| { .setup(|app| {