diff --git a/apps/app/Info.plist b/apps/app/Info.plist
index c7d4a53b0..49ab096f4 100644
--- a/apps/app/Info.plist
+++ b/apps/app/Info.plist
@@ -27,7 +27,7 @@
Owner
LSItemContentTypes
- ModrinthApp-type
+ com.modrinth.theseus-type
NSDocumentClass
NSDocument
@@ -45,7 +45,7 @@
UTTypeIcons
UTTypeIdentifier
- ModrinthApp-type
+ com.modrinth.theseus-type
UTTypeTagSpecification
public.filename-extension
diff --git a/apps/app/src/api/utils.rs b/apps/app/src/api/utils.rs
index a483b7b2d..05358cc2a 100644
--- a/apps/app/src/api/utils.rs
+++ b/apps/app/src/api/utils.rs
@@ -5,7 +5,8 @@ use theseus::{
};
use crate::api::Result;
-use std::{env, path::PathBuf};
+use dashmap::DashMap;
+use std::path::PathBuf;
pub fn init() -> tauri::plugin::TauriPlugin {
tauri::plugin::Builder::new("utils")
@@ -44,7 +45,7 @@ pub enum OS {
// Values provided should not be used directly, as they are not guaranteed to be up-to-date
#[tauri::command]
pub async fn progress_bars_list(
-) -> Result> {
+) -> Result> {
let res = theseus::EventState::list_progress_bars().await?;
Ok(res)
}
@@ -92,10 +93,28 @@ pub fn show_launcher_logs_folder() {
// This should be called once and only when the app is done booting up and ready to receive a command
// Returns a Command struct- see events.js
#[tauri::command]
+#[cfg(target_os = "macos")]
+pub async fn get_opening_command(
+ state: tauri::State<'_, crate::macos::deep_link::InitialPayload>,
+) -> Result> {
+ let payload = state.payload.lock().await;
+
+ return if let Some(payload) = payload.as_ref() {
+ tracing::info!("opening command {payload}");
+
+ Ok(Some(handler::parse_command(payload).await?))
+ } else {
+ Ok(None)
+ };
+}
+
+#[cfg(not(target_os = "macos"))]
pub async fn get_opening_command() -> Result > {
// Tauri is not CLI, we use arguments as path to file to call
let cmd_arg = env::args_os().nth(1);
+ tracing::info!("opening command {cmd_arg:?}");
+
let cmd_arg = cmd_arg.map(|path| path.to_string_lossy().to_string());
if let Some(cmd) = cmd_arg {
tracing::debug!("Opening command: {:?}", cmd);
diff --git a/apps/app/src/macos/deep_link.rs b/apps/app/src/macos/deep_link.rs
new file mode 100644
index 000000000..5383312f1
--- /dev/null
+++ b/apps/app/src/macos/deep_link.rs
@@ -0,0 +1,6 @@
+use std::sync::Arc;
+use tokio::sync::Mutex;
+
+pub struct InitialPayload {
+ pub payload: Arc>>,
+}
diff --git a/apps/app/src/macos/mod.rs b/apps/app/src/macos/mod.rs
index 229c698ce..a645c8def 100644
--- a/apps/app/src/macos/mod.rs
+++ b/apps/app/src/macos/mod.rs
@@ -1,2 +1,3 @@
+pub mod deep_link;
pub mod delegate;
pub mod window_ext;
diff --git a/apps/app/src/main.rs b/apps/app/src/main.rs
index 4f8ab49e6..dbe2630c5 100644
--- a/apps/app/src/main.rs
+++ b/apps/app/src/main.rs
@@ -89,16 +89,64 @@ fn main() {
}))
.plugin(tauri_plugin_window_state::Builder::default().build())
.setup(|app| {
- // Register deep link handler, allowing reading of modrinth:// links
- if let Err(e) = tauri_plugin_deep_link::register(
+ #[cfg(target_os = "macos")]
+ let res = {
+ use macos::deep_link::InitialPayload;
+ let mtx = std::sync::Arc::new(tokio::sync::Mutex::new(None));
+
+ app.manage(InitialPayload {
+ payload: mtx.clone(),
+ });
+
+ let mtx_copy = mtx.clone();
+ macos::delegate::register_open_file(move |filename| {
+ let mtx_copy = mtx_copy.clone();
+
+ tauri::async_runtime::spawn(async move {
+ tracing::info!("Handling file open {request}");
+
+ let mut payload = mtx_copy.lock().await;
+ if payload.is_none() {
+ *payload = Some(filename.clone());
+ }
+
+ let _ = api::utils::handle_command(filename).await;
+ });
+ })
+ .unwrap();
+
+ let mtx_copy = mtx.clone();
+ tauri_plugin_deep_link::register(
+ "modrinth",
+ move |request: String| {
+ let mtx_copy = mtx_copy.clone();
+
+ tauri::async_runtime::spawn(async move {
+ tracing::info!("Handling deep link {request}");
+
+ let mut payload = mtx_copy.lock().await;
+ if payload.is_none() {
+ *payload = Some(request.clone());
+ }
+
+ let _ = api::utils::handle_command(request).await;
+ });
+ },
+ )
+ };
+
+ #[cfg(not(target_os = "macos"))]
+ let res = tauri_plugin_deep_link::register(
"modrinth",
|request: String| {
+ tracing::info!("Handling deep link {request}");
tauri::async_runtime::spawn(api::utils::handle_command(
request,
));
},
- ) {
- // Allow it to fail- see https://github.com/FabianLars/tauri-plugin-deep-link/issues/19
+ );
+
+ if let Err(e) = res {
tracing::error!("Error registering deep link handler: {}", e);
}
@@ -117,13 +165,6 @@ fn main() {
use macos::window_ext::WindowExt;
window.set_transparent_titlebar(true);
window.position_traffic_lights(9.0, 16.0);
-
- macos::delegate::register_open_file(|filename| {
- tauri::async_runtime::spawn(
- api::utils::handle_command(filename),
- );
- })
- .unwrap();
}
}
diff --git a/packages/app-lib/src/event/emit.rs b/packages/app-lib/src/event/emit.rs
index 2b5c025de..ee20683e1 100644
--- a/packages/app-lib/src/event/emit.rs
+++ b/packages/app-lib/src/event/emit.rs
@@ -66,7 +66,7 @@ pub async fn init_loading_unsafe(
let event_state = crate::EventState::get().await?;
let key = LoadingBarId(Uuid::new_v4());
- event_state.loading_bars.write().await.insert(
+ event_state.loading_bars.insert(
key.0,
LoadingBar {
loading_bar_uuid: key.0,
@@ -121,7 +121,7 @@ pub async fn edit_loading(
) -> crate::Result<()> {
let event_state = crate::EventState::get().await?;
- if let Some(bar) = event_state.loading_bars.write().await.get_mut(&id.0) {
+ if let Some(mut bar) = event_state.loading_bars.get_mut(&id.0) {
bar.bar_type = bar_type;
bar.total = total;
bar.message = title.to_string();
@@ -152,8 +152,7 @@ pub async fn emit_loading(
) -> crate::Result<()> {
let event_state = crate::EventState::get().await?;
- let mut loading_bar = event_state.loading_bars.write().await;
- let loading_bar = match loading_bar.get_mut(&key.0) {
+ let mut loading_bar = match event_state.loading_bars.get_mut(&key.0) {
Some(f) => f,
None => {
return Err(EventError::NoLoadingBar(key.0).into());
diff --git a/packages/app-lib/src/event/mod.rs b/packages/app-lib/src/event/mod.rs
index 974416955..21b3e8a26 100644
--- a/packages/app-lib/src/event/mod.rs
+++ b/packages/app-lib/src/event/mod.rs
@@ -1,8 +1,8 @@
//! Theseus state management system
+use dashmap::DashMap;
use serde::{Deserialize, Serialize};
-use std::{collections::HashMap, path::PathBuf, sync::Arc};
+use std::{path::PathBuf, sync::Arc};
use tokio::sync::OnceCell;
-use tokio::sync::RwLock;
use uuid::Uuid;
pub mod emit;
@@ -14,7 +14,7 @@ pub struct EventState {
/// Tauri app
#[cfg(feature = "tauri")]
pub app: tauri::AppHandle,
- pub loading_bars: RwLock>,
+ pub loading_bars: DashMap,
}
impl EventState {
@@ -24,7 +24,7 @@ impl EventState {
.get_or_try_init(|| async {
Ok(Arc::new(Self {
app,
- loading_bars: RwLock::new(HashMap::new()),
+ loading_bars: DashMap::new(),
}))
})
.await
@@ -36,7 +36,7 @@ impl EventState {
EVENT_STATE
.get_or_try_init(|| async {
Ok(Arc::new(Self {
- loading_bars: RwLock::new(HashMap::new()),
+ loading_bars: DashMap::new(),
}))
})
.await
@@ -55,17 +55,10 @@ impl EventState {
}
// Values provided should not be used directly, as they are clones and are not guaranteed to be up-to-date
- pub async fn list_progress_bars() -> crate::Result>
+ pub async fn list_progress_bars() -> crate::Result>
{
let value = Self::get().await?;
- let read = value.loading_bars.read().await;
-
- let mut display_list: HashMap = HashMap::new();
- for (uuid, loading_bar) in read.iter() {
- display_list.insert(*uuid, loading_bar.clone());
- }
-
- Ok(display_list)
+ Ok(value.loading_bars.clone())
}
#[cfg(feature = "tauri")]
@@ -100,10 +93,10 @@ impl Drop for LoadingBarId {
let loader_uuid = self.0;
tokio::spawn(async move {
if let Ok(event_state) = EventState::get().await {
- let mut bars = event_state.loading_bars.write().await;
-
#[cfg(any(feature = "tauri", feature = "cli"))]
- if let Some(bar) = bars.remove(&loader_uuid) {
+ if let Some((_, bar)) =
+ event_state.loading_bars.remove(&loader_uuid)
+ {
#[cfg(feature = "tauri")]
{
let loader_uuid = bar.loading_bar_uuid;
@@ -135,7 +128,7 @@ impl Drop for LoadingBarId {
}
#[cfg(not(any(feature = "tauri", feature = "cli")))]
- bars.remove(&loader_uuid);
+ event_state.loading_bars.remove(&loader_uuid);
}
});
}