mirror of
https://github.com/Drop-OSS/drop-app.git
synced 2025-11-10 04:22:13 +10:00
chore: commit changes, still bad
This commit is contained in:
1
src-tauri/Cargo.lock
generated
1
src-tauri/Cargo.lock
generated
@ -4337,7 +4337,6 @@ checksum = "cbc931937e6ca3a06e3b6c0aa7841849b160a90351d6ab467a8b9b9959767531"
|
||||
dependencies = [
|
||||
"base64 0.22.1",
|
||||
"bytes",
|
||||
"futures-channel",
|
||||
"futures-core",
|
||||
"futures-util",
|
||||
"h2 0.4.11",
|
||||
|
||||
@ -105,7 +105,7 @@ features = ["other_errors"] # You can also use "yaml_enc"
|
||||
[dependencies.reqwest]
|
||||
version = "0.12"
|
||||
default-features = false
|
||||
features = ["json", "http2", "blocking", "rustls-tls-webpki-roots", "stream"]
|
||||
features = ["json", "http2", "rustls-tls-webpki-roots", "stream"]
|
||||
|
||||
[dependencies.serde]
|
||||
version = "1"
|
||||
|
||||
@ -1,11 +1,10 @@
|
||||
use log::{debug, error};
|
||||
use tauri::AppHandle;
|
||||
use tokio::sync::Mutex;
|
||||
|
||||
use crate::AppState;
|
||||
use crate::DropFunctionState;
|
||||
|
||||
#[tauri::command]
|
||||
pub async fn quit(app: tauri::AppHandle, state: tauri::State<'_, Mutex<AppState<'_>>>) -> Result<(), ()> {
|
||||
pub async fn quit<>(app: tauri::AppHandle, state: tauri::State<'_, DropFunctionState<'_>>) -> Result<(), ()> {
|
||||
cleanup_and_exit(&app, &state).await;
|
||||
|
||||
Ok(())
|
||||
@ -13,7 +12,7 @@ pub async fn quit(app: tauri::AppHandle, state: tauri::State<'_, Mutex<AppState<
|
||||
|
||||
pub async fn cleanup_and_exit(
|
||||
app: &AppHandle,
|
||||
state: &tauri::State<'_, Mutex<AppState<'_>>>,
|
||||
state: &tauri::State<'_, DropFunctionState<'_>>,
|
||||
) {
|
||||
debug!("cleaning up and exiting application");
|
||||
let download_manager = state.lock().await.download_manager.clone();
|
||||
|
||||
@ -1,10 +1,8 @@
|
||||
use tokio::sync::Mutex;
|
||||
|
||||
use crate::AppState;
|
||||
use crate::DropFunctionState;
|
||||
|
||||
#[tauri::command]
|
||||
pub async fn fetch_state(
|
||||
state: tauri::State<'_, Mutex<AppState<'_>>>,
|
||||
state: tauri::State<'_, DropFunctionState<'_>>,
|
||||
) -> Result<String, String> {
|
||||
let guard = state.lock().await;
|
||||
let cloned_state = serde_json::to_string(&guard.clone()).map_err(|e| e.to_string())?;
|
||||
|
||||
@ -1,22 +1,20 @@
|
||||
use tokio::sync::Mutex;
|
||||
|
||||
use crate::{database::models::data::DownloadableMetadata, AppState};
|
||||
use crate::{database::models::data::DownloadableMetadata, DropFunctionState};
|
||||
|
||||
#[tauri::command]
|
||||
pub async fn pause_downloads(state: tauri::State<'_, Mutex<AppState<'_>>>) -> Result<(), ()> {
|
||||
pub async fn pause_downloads(state: tauri::State<'_, DropFunctionState<'_>>) -> Result<(), ()> {
|
||||
state.lock().await.download_manager.pause_downloads();
|
||||
Ok(())
|
||||
}
|
||||
|
||||
#[tauri::command]
|
||||
pub async fn resume_downloads(state: tauri::State<'_, Mutex<AppState<'_>>>) -> Result<(), ()> {
|
||||
pub async fn resume_downloads(state: tauri::State<'_, DropFunctionState<'_>>) -> Result<(), ()> {
|
||||
state.lock().await.download_manager.resume_downloads();
|
||||
Ok(())
|
||||
}
|
||||
|
||||
#[tauri::command]
|
||||
pub async fn move_download_in_queue(
|
||||
state: tauri::State<'_, Mutex<AppState<'_>>>,
|
||||
state: tauri::State<'_, DropFunctionState<'_>>,
|
||||
old_index: usize,
|
||||
new_index: usize,
|
||||
) -> Result<(), ()> {
|
||||
@ -29,7 +27,7 @@ pub async fn move_download_in_queue(
|
||||
}
|
||||
|
||||
#[tauri::command]
|
||||
pub async fn cancel_game(state: tauri::State<'_, Mutex<AppState<'_>>>, meta: DownloadableMetadata) -> Result<(), ()> {
|
||||
pub async fn cancel_game(state: tauri::State<'_, DropFunctionState<'_>>, meta: DownloadableMetadata) -> Result<(), ()> {
|
||||
state.lock().await.download_manager.cancel(meta);
|
||||
Ok(())
|
||||
}
|
||||
|
||||
@ -9,7 +9,7 @@ use std::{
|
||||
use ::futures::future::join_all;
|
||||
use log::{debug, error, info, warn};
|
||||
use tauri::{AppHandle, Emitter};
|
||||
use tokio::{spawn, sync::Mutex, task::JoinHandle};
|
||||
use tokio::{runtime::Runtime, sync::Mutex};
|
||||
|
||||
use crate::{
|
||||
database::models::data::DownloadableMetadata,
|
||||
@ -75,9 +75,10 @@ pub struct DownloadManagerBuilder {
|
||||
progress: CurrentProgressObject,
|
||||
status: Arc<Mutex<DownloadManagerStatus>>,
|
||||
app_handle: AppHandle,
|
||||
runtime: Runtime,
|
||||
|
||||
current_download_agent: Option<DownloadAgent>, // Should be the only download agent in the map with the "Go" flag
|
||||
current_download_thread: Mutex<Option<JoinHandle<()>>>,
|
||||
current_download_thread: Mutex<Option<tokio::task::JoinHandle<()>>>,
|
||||
active_control_flag: Option<DownloadThreadControl>,
|
||||
}
|
||||
impl DownloadManagerBuilder {
|
||||
@ -95,13 +96,24 @@ impl DownloadManagerBuilder {
|
||||
sender: command_sender.clone(),
|
||||
progress: active_progress.clone(),
|
||||
app_handle,
|
||||
runtime: tokio::runtime::Builder::new_multi_thread()
|
||||
.worker_threads(1)
|
||||
.enable_all()
|
||||
.build()
|
||||
.unwrap(),
|
||||
|
||||
current_download_agent: None,
|
||||
current_download_thread: Mutex::new(None),
|
||||
active_control_flag: None,
|
||||
};
|
||||
|
||||
let terminator = spawn(async{ manager.manage_queue().await });
|
||||
let terminator = tauri::async_runtime::spawn(async {
|
||||
if let Err(_err) = manager.manage_queue().await {
|
||||
panic!("download manager exited with error");
|
||||
} else {
|
||||
Ok(())
|
||||
}
|
||||
});
|
||||
|
||||
DownloadManager::new(terminator, queue, active_progress, command_sender)
|
||||
}
|
||||
@ -110,7 +122,10 @@ impl DownloadManagerBuilder {
|
||||
*self.status.lock().await = status;
|
||||
}
|
||||
|
||||
async fn remove_and_cleanup_front_download(&mut self, meta: &DownloadableMetadata) -> DownloadAgent {
|
||||
async fn remove_and_cleanup_front_download(
|
||||
&mut self,
|
||||
meta: &DownloadableMetadata,
|
||||
) -> DownloadAgent {
|
||||
self.download_queue.pop_front();
|
||||
let download_agent = self.download_agent_registry.remove(meta).unwrap();
|
||||
self.cleanup_current_download().await;
|
||||
@ -126,7 +141,6 @@ impl DownloadManagerBuilder {
|
||||
|
||||
let mut download_thread_lock = self.current_download_thread.lock().await;
|
||||
*download_thread_lock = None;
|
||||
drop(download_thread_lock);
|
||||
}
|
||||
|
||||
async fn stop_and_wait_current_download(&self) {
|
||||
@ -237,12 +251,20 @@ impl DownloadManagerBuilder {
|
||||
self.active_control_flag = Some(download_agent.control_flag().await);
|
||||
self.current_download_agent = Some(download_agent.clone());
|
||||
|
||||
info!("fetched control flag");
|
||||
|
||||
let sender = self.sender.clone();
|
||||
|
||||
info!("cloned sender");
|
||||
|
||||
let mut download_thread_lock = self.current_download_thread.lock().await;
|
||||
info!("acquired download thread lock");
|
||||
let app_handle = self.app_handle.clone();
|
||||
|
||||
*download_thread_lock = Some(spawn(async move {
|
||||
info!("starting download agent thread");
|
||||
|
||||
*download_thread_lock = Some(self.runtime.spawn(async move {
|
||||
info!("started download agent thread");
|
||||
match download_agent.download(&app_handle).await {
|
||||
// Ok(true) is for completed and exited properly
|
||||
Ok(true) => {
|
||||
@ -285,6 +307,8 @@ impl DownloadManagerBuilder {
|
||||
self.set_status(DownloadManagerStatus::Downloading).await;
|
||||
let active_control_flag = self.active_control_flag.clone().unwrap();
|
||||
active_control_flag.set(DownloadThreadControlFlag::Go);
|
||||
|
||||
// download_thread_lock.take().unwrap().await;
|
||||
}
|
||||
async fn manage_stop_signal(&mut self) {
|
||||
debug!("got signal Stop");
|
||||
@ -311,7 +335,8 @@ impl DownloadManagerBuilder {
|
||||
current_agent.on_error(&self.app_handle, &error).await;
|
||||
|
||||
self.stop_and_wait_current_download().await;
|
||||
self.remove_and_cleanup_front_download(¤t_agent.metadata()).await;
|
||||
self.remove_and_cleanup_front_download(¤t_agent.metadata())
|
||||
.await;
|
||||
}
|
||||
self.set_status(DownloadManagerStatus::Error).await;
|
||||
}
|
||||
@ -365,18 +390,17 @@ impl DownloadManagerBuilder {
|
||||
}
|
||||
async fn push_ui_queue_update(&self) {
|
||||
let queue = &self.download_queue.read();
|
||||
let queue_objs = join_all(queue
|
||||
.iter()
|
||||
.map(async |key| {
|
||||
let val = self.download_agent_registry.get(key).unwrap();
|
||||
QueueUpdateEventQueueData {
|
||||
meta: DownloadableMetadata::clone(key),
|
||||
status: val.status().await,
|
||||
progress: val.progress().await.get_progress(),
|
||||
current: val.progress().await.sum(),
|
||||
max: val.progress().await.get_max(),
|
||||
}
|
||||
})).await;
|
||||
let queue_objs = join_all(queue.iter().map(async |key| {
|
||||
let val = self.download_agent_registry.get(key).unwrap();
|
||||
QueueUpdateEventQueueData {
|
||||
meta: DownloadableMetadata::clone(key),
|
||||
status: val.status().await,
|
||||
progress: val.progress().await.get_progress(),
|
||||
current: val.progress().await.sum(),
|
||||
max: val.progress().await.get_max(),
|
||||
}
|
||||
}))
|
||||
.await;
|
||||
|
||||
let event_data = QueueUpdateEvent { queue: queue_objs };
|
||||
self.app_handle.emit("update_queue", event_data).unwrap();
|
||||
|
||||
@ -9,7 +9,7 @@ use std::{
|
||||
|
||||
use log::{debug, info};
|
||||
use serde::Serialize;
|
||||
use tokio::task::{JoinError, JoinHandle};
|
||||
use tauri::async_runtime::JoinHandle;
|
||||
|
||||
use crate::{
|
||||
database::models::data::DownloadableMetadata,
|
||||
@ -170,7 +170,7 @@ impl DownloadManager {
|
||||
pub fn resume_downloads(&self) {
|
||||
self.command_sender.send(DownloadManagerSignal::Go).unwrap();
|
||||
}
|
||||
pub async fn ensure_terminated(&self) -> Result<Result<(), ()>, JoinError> {
|
||||
pub async fn ensure_terminated(&self) -> Result<Result<(), ()>, tauri::Error> {
|
||||
self.command_sender
|
||||
.send(DownloadManagerSignal::Finish)
|
||||
.unwrap();
|
||||
|
||||
@ -1,16 +1,11 @@
|
||||
use serde::Deserialize;
|
||||
use tauri::AppHandle;
|
||||
use tokio::sync::Mutex;
|
||||
|
||||
use crate::{
|
||||
AppState,
|
||||
database::{db::borrow_db_mut_checked, models::data::GameVersion},
|
||||
error::{library_error::LibraryError, remote_access_error::RemoteAccessError},
|
||||
games::library::{
|
||||
database::{db::borrow_db_mut_checked, models::data::GameVersion}, error::{library_error::LibraryError, remote_access_error::RemoteAccessError}, games::library::{
|
||||
fetch_game_logic_offline, fetch_library_logic_offline, get_current_meta,
|
||||
uninstall_game_logic,
|
||||
},
|
||||
offline,
|
||||
}, offline, DropFunctionState
|
||||
};
|
||||
|
||||
use super::{
|
||||
@ -23,7 +18,7 @@ use super::{
|
||||
|
||||
#[tauri::command]
|
||||
pub async fn fetch_library(
|
||||
state: tauri::State<'_, Mutex<AppState<'_>>>,
|
||||
state: tauri::State<'_, DropFunctionState<'_>>,
|
||||
) -> Result<Vec<Game>, RemoteAccessError> {
|
||||
offline!(
|
||||
state,
|
||||
@ -37,7 +32,7 @@ pub async fn fetch_library(
|
||||
#[tauri::command]
|
||||
pub async fn fetch_game(
|
||||
game_id: String,
|
||||
state: tauri::State<'_, Mutex<AppState<'_>>>,
|
||||
state: tauri::State<'_, DropFunctionState<'_>>,
|
||||
) -> Result<FetchGameStruct, RemoteAccessError> {
|
||||
offline!(
|
||||
state,
|
||||
@ -68,7 +63,7 @@ pub async fn uninstall_game(game_id: String, app_handle: AppHandle) -> Result<()
|
||||
#[tauri::command]
|
||||
pub async fn fetch_game_verion_options(
|
||||
game_id: String,
|
||||
state: tauri::State<'_, Mutex<AppState<'_>>>,
|
||||
state: tauri::State<'_, DropFunctionState<'_>>,
|
||||
) -> Result<Vec<GameVersion>, RemoteAccessError> {
|
||||
fetch_game_verion_options_logic(game_id, state).await
|
||||
}
|
||||
|
||||
@ -1,6 +1,6 @@
|
||||
use std::{
|
||||
path::PathBuf,
|
||||
sync::{Arc, Mutex},
|
||||
sync::Arc,
|
||||
};
|
||||
|
||||
use crate::{
|
||||
@ -8,8 +8,7 @@ use crate::{
|
||||
download_manager::{
|
||||
download_manager_frontend::DownloadManagerSignal, downloadable::Downloadable,
|
||||
},
|
||||
error::download_manager_error::DownloadManagerError,
|
||||
AppState,
|
||||
error::download_manager_error::DownloadManagerError, DropFunctionState,
|
||||
};
|
||||
|
||||
use super::download_agent::GameDownloadAgent;
|
||||
@ -19,9 +18,9 @@ pub async fn download_game(
|
||||
game_id: String,
|
||||
game_version: String,
|
||||
install_dir: usize,
|
||||
state: tauri::State<'_, Mutex<AppState<'_>>>,
|
||||
state: tauri::State<'_, DropFunctionState<'_>>,
|
||||
) -> Result<(), DownloadManagerError<DownloadManagerSignal>> {
|
||||
let sender = state.lock().unwrap().download_manager.get_sender();
|
||||
let sender = state.lock().await.download_manager.get_sender();
|
||||
let game_download_agent = Arc::new(Box::new(GameDownloadAgent::new_from_index(
|
||||
game_id,
|
||||
game_version,
|
||||
@ -30,7 +29,7 @@ pub async fn download_game(
|
||||
).await) as Box<dyn Downloadable + Send + Sync>);
|
||||
Ok(state
|
||||
.lock()
|
||||
.unwrap()
|
||||
.await
|
||||
.download_manager
|
||||
.queue_download(game_download_agent)?)
|
||||
}
|
||||
@ -38,7 +37,7 @@ pub async fn download_game(
|
||||
#[tauri::command]
|
||||
pub async fn resume_download(
|
||||
game_id: String,
|
||||
state: tauri::State<'_, Mutex<AppState<'_>>>,
|
||||
state: tauri::State<'_, DropFunctionState<'_>>,
|
||||
) -> Result<(), DownloadManagerError<DownloadManagerSignal>> {
|
||||
let s = borrow_db_checked().await
|
||||
.applications
|
||||
@ -56,7 +55,7 @@ pub async fn resume_download(
|
||||
install_dir,
|
||||
} => (version_name, install_dir),
|
||||
};
|
||||
let sender = state.lock().unwrap().download_manager.get_sender();
|
||||
let sender = state.lock().await.download_manager.get_sender();
|
||||
let parent_dir: PathBuf = install_dir.into();
|
||||
let game_download_agent = Arc::new(Box::new(GameDownloadAgent::new(
|
||||
game_id,
|
||||
@ -66,7 +65,7 @@ pub async fn resume_download(
|
||||
)) as Box<dyn Downloadable + Send + Sync>);
|
||||
Ok(state
|
||||
.lock()
|
||||
.unwrap()
|
||||
.await
|
||||
.download_manager
|
||||
.queue_download(game_download_agent)?)
|
||||
}
|
||||
|
||||
@ -1,5 +1,6 @@
|
||||
use crate::DB;
|
||||
use crate::auth::generate_authorization_header;
|
||||
use crate::database::db::{borrow_db_checked, borrow_db_mut_checked};
|
||||
use crate::database::db::{DatabaseImpls, borrow_db_checked, borrow_db_mut_checked};
|
||||
use crate::database::models::data::{
|
||||
ApplicationTransientStatus, DownloadType, DownloadableMetadata,
|
||||
};
|
||||
@ -105,6 +106,7 @@ impl GameDownloadAgent {
|
||||
|
||||
// Blocking
|
||||
pub async fn download(&self, app_handle: &AppHandle) -> Result<bool, ApplicationDownloadError> {
|
||||
debug!("starting download");
|
||||
self.setup_download().await?;
|
||||
self.set_progress_object_params();
|
||||
let timer = Instant::now();
|
||||
@ -268,11 +270,19 @@ impl GameDownloadAgent {
|
||||
self.id, max_download_threads
|
||||
);
|
||||
|
||||
let client = &reqwest::Client::new();
|
||||
let base_url = DB
|
||||
.fetch_base_url()
|
||||
.await
|
||||
.join("/api/v1/client/chunk")
|
||||
.unwrap();
|
||||
let client = reqwest::Client::new();
|
||||
let client_ref = unsafe { extend_lifetime(&client) };
|
||||
|
||||
let rt = tokio::runtime::Builder::new_multi_thread()
|
||||
.worker_threads(max_download_threads)
|
||||
.thread_name("drop-download-thread")
|
||||
.enable_io()
|
||||
.enable_time()
|
||||
.build()
|
||||
.map_err(|e| {
|
||||
warn!("failed to create download scheduler: {e}");
|
||||
@ -288,8 +298,6 @@ impl GameDownloadAgent {
|
||||
|
||||
let context_map = self.context_map.lock().unwrap();
|
||||
for (index, context) in contexts.iter().enumerate() {
|
||||
let client = client.clone();
|
||||
|
||||
let progress = self.progress.get(index);
|
||||
let progress_handle = ProgressHandle::new(progress, self.progress.clone());
|
||||
|
||||
@ -308,30 +316,22 @@ impl GameDownloadAgent {
|
||||
*/
|
||||
let context = unsafe { extend_lifetime(context) };
|
||||
let self_static = unsafe { extend_lifetime(self) };
|
||||
let mut base_url = base_url.clone();
|
||||
rt.spawn(async move {
|
||||
let request = match make_request(
|
||||
&client,
|
||||
&["/api/v1/client/chunk"],
|
||||
&[
|
||||
{
|
||||
let mut query = base_url.query_pairs_mut();
|
||||
let query_params = [
|
||||
("id", &context.game_id),
|
||||
("version", &context.version),
|
||||
("name", &context.file_name),
|
||||
("chunk", &context.index.to_string()),
|
||||
],
|
||||
async |r| r,
|
||||
)
|
||||
.await
|
||||
{
|
||||
Ok(request) => request,
|
||||
Err(e) => {
|
||||
sender
|
||||
.send(DownloadManagerSignal::Error(
|
||||
ApplicationDownloadError::Communication(e),
|
||||
))
|
||||
.unwrap();
|
||||
return;
|
||||
];
|
||||
for (param, val) in query_params {
|
||||
query.append_pair(param.as_ref(), val.as_ref());
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
let request = client_ref.get(base_url);
|
||||
|
||||
match download_game_chunk(
|
||||
context,
|
||||
@ -356,7 +356,6 @@ impl GameDownloadAgent {
|
||||
|
||||
let mut newly_completed = Vec::new();
|
||||
while let Some(completed_checksum) = rx.recv().await {
|
||||
println!("completed checksum {}", completed_checksum);
|
||||
newly_completed.push(completed_checksum);
|
||||
}
|
||||
|
||||
@ -409,6 +408,7 @@ impl Downloadable for GameDownloadAgent {
|
||||
}
|
||||
|
||||
async fn download(&self, app_handle: &AppHandle) -> Result<bool, ApplicationDownloadError> {
|
||||
debug!("starting download from downloadable trait");
|
||||
*self.status.lock().unwrap() = DownloadStatus::Downloading;
|
||||
self.download(app_handle).await
|
||||
}
|
||||
|
||||
@ -6,9 +6,9 @@ use crate::error::application_download_error::ApplicationDownloadError;
|
||||
use crate::error::drop_server_error::DropServerError;
|
||||
use crate::error::remote_access_error::RemoteAccessError;
|
||||
use crate::games::downloads::manifest::DropDownloadContext;
|
||||
use crate::remote::auth::generate_authorization_header;
|
||||
use crate::remote::auth::{generate_authorization_header, generate_authorization_header_part};
|
||||
use futures::TryStreamExt;
|
||||
use log::{debug, warn};
|
||||
use log::{debug, info, warn};
|
||||
use md5::{Context, Digest};
|
||||
use reqwest::RequestBuilder;
|
||||
use tokio::fs::{File, OpenOptions};
|
||||
@ -97,6 +97,7 @@ where
|
||||
}
|
||||
|
||||
let mut bytes_read = self.source.read(&mut copy_buf).await?;
|
||||
info!("read {}", bytes_read);
|
||||
current_size += bytes_read;
|
||||
|
||||
if current_size > self.size {
|
||||
@ -139,8 +140,11 @@ pub async fn download_game_chunk(
|
||||
progress.set(0);
|
||||
return Ok(false);
|
||||
}
|
||||
|
||||
let header_generator = generate_authorization_header_part().await;
|
||||
|
||||
let response = request
|
||||
.header("Authorization", generate_authorization_header().await)
|
||||
.header("Authorization", header_generator())
|
||||
.send()
|
||||
.await
|
||||
.map_err(|e| ApplicationDownloadError::Communication(e.into()))?;
|
||||
|
||||
@ -5,9 +5,7 @@ use serde::{Deserialize, Serialize};
|
||||
use tauri::AppHandle;
|
||||
use tauri::Emitter;
|
||||
use tokio::spawn;
|
||||
use tokio::sync::Mutex;
|
||||
|
||||
use crate::AppState;
|
||||
use crate::database::db::{borrow_db_checked, borrow_db_mut_checked};
|
||||
use crate::database::models::data::{
|
||||
ApplicationTransientStatus, DownloadableMetadata, GameDownloadStatus, GameVersion,
|
||||
@ -18,6 +16,7 @@ use crate::games::state::{GameStatusManager, GameStatusWithTransient};
|
||||
use crate::remote::auth::generate_authorization_header;
|
||||
use crate::remote::cache::{cache_object, get_cached_object, get_cached_object_db};
|
||||
use crate::remote::requests::make_request;
|
||||
use crate::DropFunctionState;
|
||||
use bitcode::{Decode, Encode};
|
||||
|
||||
#[derive(Serialize, Deserialize, Debug)]
|
||||
@ -73,7 +72,7 @@ pub struct StatsUpdateEvent {
|
||||
}
|
||||
|
||||
pub async fn fetch_library_logic(
|
||||
state: tauri::State<'_, Mutex<AppState<'_>>>,
|
||||
state: tauri::State<'_, DropFunctionState<'_>>,
|
||||
) -> Result<Vec<Game>, RemoteAccessError> {
|
||||
let header = generate_authorization_header().await;
|
||||
|
||||
@ -125,7 +124,7 @@ pub async fn fetch_library_logic(
|
||||
Ok(games)
|
||||
}
|
||||
pub async fn fetch_library_logic_offline(
|
||||
_state: tauri::State<'_, Mutex<AppState<'_>>>,
|
||||
_state: tauri::State<'_, DropFunctionState<'_>>,
|
||||
) -> Result<Vec<Game>, RemoteAccessError> {
|
||||
let mut games: Vec<Game> = get_cached_object("library").await?;
|
||||
|
||||
@ -142,7 +141,7 @@ pub async fn fetch_library_logic_offline(
|
||||
}
|
||||
pub async fn fetch_game_logic(
|
||||
id: String,
|
||||
state: tauri::State<'_, Mutex<AppState<'_>>>,
|
||||
state: tauri::State<'_, DropFunctionState<'_>>,
|
||||
) -> Result<FetchGameStruct, RemoteAccessError> {
|
||||
let mut state_handle = state.lock().await;
|
||||
|
||||
@ -222,7 +221,7 @@ pub async fn fetch_game_logic(
|
||||
|
||||
pub async fn fetch_game_logic_offline(
|
||||
id: String,
|
||||
_state: tauri::State<'_, Mutex<AppState<'_>>>,
|
||||
_state: tauri::State<'_, DropFunctionState<'_>>,
|
||||
) -> Result<FetchGameStruct, RemoteAccessError> {
|
||||
let handle = borrow_db_checked().await;
|
||||
let metadata_option = handle.applications.installed_game_version.get(&id);
|
||||
@ -253,7 +252,7 @@ pub async fn fetch_game_logic_offline(
|
||||
|
||||
pub async fn fetch_game_verion_options_logic(
|
||||
game_id: String,
|
||||
state: tauri::State<'_, Mutex<AppState<'_>>>,
|
||||
state: tauri::State<'_, DropFunctionState<'_>>,
|
||||
) -> Result<Vec<GameVersion>, RemoteAccessError> {
|
||||
let client = reqwest::Client::new();
|
||||
|
||||
|
||||
@ -72,7 +72,6 @@ use tauri::tray::TrayIconBuilder;
|
||||
use tauri::{AppHandle, Manager, RunEvent, WindowEvent};
|
||||
use tauri_plugin_deep_link::DeepLinkExt;
|
||||
use tauri_plugin_dialog::DialogExt;
|
||||
use tokio::runtime::Handle;
|
||||
use tokio::sync::Mutex;
|
||||
|
||||
#[derive(Clone, Copy, Serialize, Eq, PartialEq)]
|
||||
@ -220,6 +219,7 @@ async fn setup(handle: AppHandle) -> AppState<'static> {
|
||||
}
|
||||
|
||||
pub static DB: OnceCellDatabase = OnceCellDatabase::new();
|
||||
pub type DropFunctionState<'a> = Mutex<AppState<'a>>;
|
||||
|
||||
pub fn custom_panic_handler(e: &PanicHookInfo) -> Option<()> {
|
||||
let crash_file = DATA_ROOT_DIR.join(format!(
|
||||
@ -238,15 +238,12 @@ pub fn custom_panic_handler(e: &PanicHookInfo) -> Option<()> {
|
||||
}
|
||||
|
||||
#[cfg_attr(mobile, tauri::mobile_entry_point)]
|
||||
pub async fn run() {
|
||||
pub fn run() {
|
||||
panic::set_hook(Box::new(|e| {
|
||||
let _ = custom_panic_handler(e);
|
||||
println!("{e}");
|
||||
}));
|
||||
|
||||
DB.init(async { DatabaseInterface::set_up_database().await })
|
||||
.await;
|
||||
|
||||
let mut builder = tauri::Builder::default()
|
||||
.plugin(tauri_plugin_opener::init())
|
||||
.plugin(tauri_plugin_os::init())
|
||||
@ -318,9 +315,11 @@ pub async fn run() {
|
||||
))
|
||||
.setup(|app| {
|
||||
let app = app.handle().clone();
|
||||
let runtime = Handle::current();
|
||||
|
||||
runtime.spawn(async move {
|
||||
tauri::async_runtime::spawn(async move {
|
||||
DB.init(async { DatabaseInterface::set_up_database().await })
|
||||
.await;
|
||||
|
||||
let state = setup(app.clone()).await;
|
||||
info!("initialized drop client");
|
||||
if !app.manage(Mutex::new(state)) {
|
||||
@ -363,18 +362,24 @@ pub async fn run() {
|
||||
)
|
||||
.unwrap();
|
||||
|
||||
run_on_tray(|| {
|
||||
let tray_app_handle = app.clone();
|
||||
run_on_tray(move || {
|
||||
TrayIconBuilder::new()
|
||||
.icon(app.default_window_icon().unwrap().clone())
|
||||
.icon(tray_app_handle.default_window_icon().unwrap().clone())
|
||||
.menu(&menu)
|
||||
.on_menu_event(|app, event| {
|
||||
let tray_app_handle = app.clone();
|
||||
tauri::async_runtime::block_on(async move {
|
||||
match event.id.as_ref() {
|
||||
"open" => {
|
||||
app.webview_windows().get("main").unwrap().show().unwrap();
|
||||
}
|
||||
"quit" => {
|
||||
cleanup_and_exit(app, &app.state()).await;
|
||||
cleanup_and_exit(
|
||||
&tray_app_handle,
|
||||
&tray_app_handle.state(),
|
||||
)
|
||||
.await;
|
||||
}
|
||||
|
||||
_ => {
|
||||
@ -383,7 +388,7 @@ pub async fn run() {
|
||||
}
|
||||
})
|
||||
})
|
||||
.build(&app)
|
||||
.build(&tray_app_handle)
|
||||
.expect("error while setting up tray menu");
|
||||
});
|
||||
|
||||
@ -422,7 +427,7 @@ pub async fn run() {
|
||||
})
|
||||
.register_asynchronous_uri_scheme_protocol("object", move |ctx, request, responder| {
|
||||
tauri::async_runtime::block_on(async move {
|
||||
let state: tauri::State<'_, Mutex<AppState>> = ctx.app_handle().state();
|
||||
let state = ctx.app_handle().state::<DropFunctionState<'_>>();
|
||||
offline!(
|
||||
state,
|
||||
fetch_object,
|
||||
@ -435,7 +440,7 @@ pub async fn run() {
|
||||
})
|
||||
.register_asynchronous_uri_scheme_protocol("server", move |ctx, request, responder| {
|
||||
tauri::async_runtime::block_on(async move {
|
||||
let state: tauri::State<'_, Mutex<AppState>> = ctx.app_handle().state();
|
||||
let state = ctx.app_handle().state::<DropFunctionState<'_>>();
|
||||
offline!(
|
||||
state,
|
||||
handle_server_proto,
|
||||
|
||||
@ -1,7 +1,12 @@
|
||||
// Prevents additional console window on Windows in release, DO NOT REMOVE!!
|
||||
#![cfg_attr(not(debug_assertions), windows_subsystem = "windows")]
|
||||
|
||||
#[tokio::main]
|
||||
async fn main() {
|
||||
drop_app_lib::run().await
|
||||
fn main() {
|
||||
let global_runtime = tokio::runtime::Builder::new_multi_thread()
|
||||
.worker_threads(32)
|
||||
.enable_all()
|
||||
.build()
|
||||
.unwrap();
|
||||
tauri::async_runtime::set(global_runtime.handle().clone());
|
||||
drop_app_lib::run()
|
||||
}
|
||||
|
||||
@ -1,11 +1,9 @@
|
||||
use tokio::sync::Mutex;
|
||||
|
||||
use crate::{AppState, error::process_error::ProcessError};
|
||||
use crate::{error::process_error::ProcessError, DropFunctionState};
|
||||
|
||||
#[tauri::command]
|
||||
pub async fn launch_game(
|
||||
id: String,
|
||||
state: tauri::State<'_, Mutex<AppState<'_>>>,
|
||||
state: tauri::State<'_, DropFunctionState<'_>>,
|
||||
) -> Result<(), ProcessError> {
|
||||
let state_lock = state.lock().await;
|
||||
let mut process_manager_lock = state_lock.process_manager.lock().await;
|
||||
@ -30,7 +28,7 @@ pub async fn launch_game(
|
||||
#[tauri::command]
|
||||
pub async fn kill_game(
|
||||
game_id: String,
|
||||
state: tauri::State<'_, Mutex<AppState<'_>>>,
|
||||
state: tauri::State<'_, DropFunctionState<'_>>,
|
||||
) -> Result<(), ProcessError> {
|
||||
let state_lock = state.lock().await;
|
||||
let mut process_manager_lock = state_lock.process_manager.lock().await;
|
||||
@ -42,7 +40,7 @@ pub async fn kill_game(
|
||||
#[tauri::command]
|
||||
pub async fn open_process_logs(
|
||||
game_id: String,
|
||||
state: tauri::State<'_, Mutex<AppState<'_>>>,
|
||||
state: tauri::State<'_, DropFunctionState<'_>>,
|
||||
) -> Result<(), ProcessError> {
|
||||
let state_lock = state.lock().await;
|
||||
let mut process_manager_lock = state_lock.process_manager.lock().await;
|
||||
|
||||
@ -16,19 +16,16 @@ use serde::{Deserialize, Serialize};
|
||||
use shared_child::SharedChild;
|
||||
use tauri::{AppHandle, Emitter, Manager};
|
||||
use tauri_plugin_opener::OpenerExt;
|
||||
use tokio::{spawn, sync::Mutex};
|
||||
use tokio::spawn;
|
||||
|
||||
use crate::{
|
||||
AppState, DB,
|
||||
database::{
|
||||
db::{DATA_ROOT_DIR, borrow_db_mut_checked},
|
||||
db::{borrow_db_mut_checked, DATA_ROOT_DIR},
|
||||
models::data::{
|
||||
ApplicationTransientStatus, DownloadType, DownloadableMetadata, GameDownloadStatus,
|
||||
GameVersion,
|
||||
},
|
||||
},
|
||||
error::process_error::ProcessError,
|
||||
games::{library::push_game_update, state::GameStatusManager},
|
||||
}, error::process_error::ProcessError, games::{library::push_game_update, state::GameStatusManager}, DropFunctionState, DB
|
||||
};
|
||||
|
||||
pub struct RunningProcess {
|
||||
@ -337,7 +334,7 @@ impl ProcessManager<'_> {
|
||||
spawn(async move {
|
||||
let result: Result<ExitStatus, std::io::Error> = launch_process_handle.wait();
|
||||
|
||||
let app_state = wait_thread_apphandle.state::<Mutex<AppState>>();
|
||||
let app_state = wait_thread_apphandle.state::<tauri::State<'_, DropFunctionState<'_>>>();
|
||||
let app_state_handle = app_state.lock().await;
|
||||
|
||||
let mut process_manager_handle = app_state_handle.process_manager.lock().await;
|
||||
|
||||
@ -1,15 +1,15 @@
|
||||
use std::{collections::HashMap, env, sync::Mutex};
|
||||
use std::{collections::HashMap, env};
|
||||
|
||||
use chrono::Utc;
|
||||
use droplet_rs::ssl::sign_nonce;
|
||||
use gethostname::gethostname;
|
||||
use log::{debug, error, warn};
|
||||
use log::{debug, error, info, warn};
|
||||
use serde::{Deserialize, Serialize};
|
||||
use tauri::{AppHandle, Emitter, Manager};
|
||||
use url::Url;
|
||||
|
||||
use crate::{
|
||||
AppState, AppStatus, User,
|
||||
AppStatus, DropFunctionState, User,
|
||||
database::{
|
||||
db::{borrow_db_checked, borrow_db_mut_checked},
|
||||
models::data::DatabaseAuth,
|
||||
@ -50,16 +50,23 @@ struct HandshakeResponse {
|
||||
}
|
||||
|
||||
pub async fn generate_authorization_header() -> String {
|
||||
let func = generate_authorization_header_part().await;
|
||||
func()
|
||||
}
|
||||
|
||||
pub async fn generate_authorization_header_part() -> Box<dyn FnOnce() -> String> {
|
||||
let certs = {
|
||||
let db = borrow_db_checked().await;
|
||||
db.auth.clone().unwrap()
|
||||
};
|
||||
|
||||
let nonce = Utc::now().timestamp_millis().to_string();
|
||||
Box::new(move || {
|
||||
let nonce = Utc::now().timestamp_millis().to_string();
|
||||
|
||||
let signature = sign_nonce(certs.private, nonce.clone()).unwrap();
|
||||
let signature = sign_nonce(certs.private, nonce.clone()).unwrap();
|
||||
|
||||
format!("Nonce {} {} {}", certs.client_id, nonce, signature)
|
||||
format!("Nonce {} {} {}", certs.client_id, nonce, signature)
|
||||
})
|
||||
}
|
||||
|
||||
pub async fn fetch_user() -> Result<User, RemoteAccessError> {
|
||||
@ -156,11 +163,11 @@ pub async fn recieve_handshake(app: AppHandle, path: String) {
|
||||
return;
|
||||
}
|
||||
|
||||
let app_state = app.state::<Mutex<AppState>>();
|
||||
let app_state = app.state::<DropFunctionState<'_>>();
|
||||
|
||||
let (app_status, user) = setup().await;
|
||||
|
||||
let mut state_lock = app_state.lock().unwrap();
|
||||
let mut state_lock = app_state.lock().await;
|
||||
state_lock.status = app_status;
|
||||
state_lock.user = user;
|
||||
|
||||
@ -185,20 +192,20 @@ pub async fn auth_initiate_logic() -> Result<(), RemoteAccessError> {
|
||||
]),
|
||||
};
|
||||
|
||||
let client = reqwest::blocking::Client::new();
|
||||
let response = client.post(endpoint.to_string()).json(&body).send()?;
|
||||
let client = reqwest::Client::new();
|
||||
let response = client.post(endpoint.to_string()).json(&body).send().await?;
|
||||
|
||||
if response.status() != 200 {
|
||||
let data: DropServerError = response.json()?;
|
||||
let data: DropServerError = response.json().await?;
|
||||
error!("could not start handshake: {}", data.status_message);
|
||||
|
||||
return Err(RemoteAccessError::HandshakeFailed(data.status_message));
|
||||
}
|
||||
|
||||
let redir_url = response.text()?;
|
||||
let redir_url = response.text().await?;
|
||||
let complete_redir_url = base_url.join(&redir_url)?;
|
||||
|
||||
debug!("opening web browser to continue authentication");
|
||||
info!("opening web browser to continue authentication: {}", complete_redir_url);
|
||||
webbrowser::open(complete_redir_url.as_ref()).unwrap();
|
||||
|
||||
Ok(())
|
||||
|
||||
@ -1,11 +1,10 @@
|
||||
use log::debug;
|
||||
use reqwest::Client;
|
||||
use tauri::{AppHandle, Emitter, Manager};
|
||||
use tokio::sync::Mutex;
|
||||
use url::Url;
|
||||
|
||||
use crate::{
|
||||
AppState, AppStatus,
|
||||
AppStatus, DropFunctionState,
|
||||
database::db::{borrow_db_checked, borrow_db_mut_checked},
|
||||
error::remote_access_error::RemoteAccessError,
|
||||
remote::{auth::generate_authorization_header, requests::make_request},
|
||||
@ -20,7 +19,7 @@ use super::{
|
||||
#[tauri::command]
|
||||
pub async fn use_remote(
|
||||
url: String,
|
||||
state: tauri::State<'_, Mutex<AppState<'_>>>,
|
||||
state: tauri::State<'_, DropFunctionState<'_>>,
|
||||
) -> Result<(), RemoteAccessError> {
|
||||
use_remote_logic(url, state).await
|
||||
}
|
||||
@ -70,7 +69,7 @@ pub async fn sign_out(app: AppHandle) {
|
||||
|
||||
// Update app state
|
||||
{
|
||||
let app_state = app.state::<Mutex<AppState>>();
|
||||
let app_state = app.state::<DropFunctionState<'_>>();
|
||||
let mut app_state_handle = app_state.lock().await;
|
||||
app_state_handle.status = AppStatus::SignedOut;
|
||||
app_state_handle.user = None;
|
||||
@ -81,7 +80,7 @@ pub async fn sign_out(app: AppHandle) {
|
||||
}
|
||||
|
||||
#[tauri::command]
|
||||
pub async fn retry_connect(state: tauri::State<'_, Mutex<AppState<'_>>>) -> Result<(), ()> {
|
||||
pub async fn retry_connect(state: tauri::State<'_, DropFunctionState<'_>>) -> Result<(), ()> {
|
||||
let (app_status, user) = setup().await;
|
||||
|
||||
let mut guard = state.lock().await;
|
||||
|
||||
@ -1,7 +1,7 @@
|
||||
use std::str::FromStr;
|
||||
|
||||
use http::{uri::PathAndQuery, Request, Response, StatusCode, Uri};
|
||||
use reqwest::blocking::Client;
|
||||
use reqwest::Client;
|
||||
use tauri::UriSchemeResponder;
|
||||
|
||||
use crate::database::db::borrow_db_checked;
|
||||
@ -44,10 +44,11 @@ pub async fn handle_server_proto(request: Request<Vec<u8>>, responder: UriScheme
|
||||
.header("Authorization", format!("Bearer {web_token}"))
|
||||
.headers(request.headers().clone())
|
||||
.send()
|
||||
.await
|
||||
.unwrap();
|
||||
|
||||
let response_status = response.status();
|
||||
let response_body = response.bytes().unwrap();
|
||||
let response_body = response.bytes().await.unwrap();
|
||||
|
||||
let http_response = Response::builder()
|
||||
.status(response_status)
|
||||
|
||||
@ -1,11 +1,9 @@
|
||||
use log::{debug, warn};
|
||||
use log::{debug, info, warn};
|
||||
use serde::Deserialize;
|
||||
use tokio::sync::Mutex;
|
||||
use url::Url;
|
||||
|
||||
use crate::{
|
||||
AppState, AppStatus, database::db::borrow_db_mut_checked,
|
||||
error::remote_access_error::RemoteAccessError,
|
||||
database::db::borrow_db_mut_checked, error::remote_access_error::RemoteAccessError, AppStatus, DropFunctionState
|
||||
};
|
||||
|
||||
#[derive(Deserialize)]
|
||||
@ -16,16 +14,16 @@ struct DropHealthcheck {
|
||||
|
||||
pub async fn use_remote_logic(
|
||||
url: String,
|
||||
state: tauri::State<'_, Mutex<AppState<'_>>>,
|
||||
state: tauri::State<'_, DropFunctionState<'_>>,
|
||||
) -> Result<(), RemoteAccessError> {
|
||||
debug!("connecting to url {url}");
|
||||
info!("connecting to url {url}");
|
||||
let base_url = Url::parse(&url)?;
|
||||
|
||||
// Test Drop url
|
||||
let test_endpoint = base_url.join("/api/v1")?;
|
||||
let response = reqwest::blocking::get(test_endpoint.to_string())?;
|
||||
let response = reqwest::get(test_endpoint.to_string()).await?;
|
||||
|
||||
let result: DropHealthcheck = response.json()?;
|
||||
let result: DropHealthcheck = response.json().await?;
|
||||
|
||||
if result.app_name != "Drop" {
|
||||
warn!("user entered drop endpoint that connected, but wasn't identified as Drop");
|
||||
|
||||
Reference in New Issue
Block a user