mirror of
https://github.com/infinilabs/coco-app.git
synced 2025-12-22 22:39:24 +01:00
Compare commits
1 Commits
main
...
steve/fix/
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
1759e0e56e |
@@ -17,6 +17,8 @@ Information about release notes of Coco App is provided here.
|
||||
|
||||
### ✈️ Improvements
|
||||
|
||||
- refactor: add a timeout to open() #1025
|
||||
|
||||
## 0.10.0 (2025-12-19)
|
||||
|
||||
### ❌ Breaking changes
|
||||
|
||||
@@ -148,152 +148,171 @@ pub(crate) async fn open(
|
||||
extra_args: Option<HashMap<String, Json>>,
|
||||
) -> Result<(), String> {
|
||||
use crate::util::open as homemade_tauri_shell_open;
|
||||
use std::process::Command;
|
||||
use tokio::process::Command;
|
||||
use tokio::time::Duration;
|
||||
use tokio::time::timeout;
|
||||
|
||||
match on_opened {
|
||||
OnOpened::Application { app_path } => {
|
||||
log::debug!("open application [{}]", app_path);
|
||||
let on_opened_clone = on_opened.clone();
|
||||
// Put the main logic in an async closure so that we can `time::timeout()`
|
||||
// it
|
||||
let async_closure = async move {
|
||||
match on_opened_clone {
|
||||
OnOpened::Application { app_path } => {
|
||||
log::debug!("open application [{}]", app_path);
|
||||
|
||||
homemade_tauri_shell_open(tauri_app_handle.clone(), app_path).await?
|
||||
}
|
||||
OnOpened::Document { url } => {
|
||||
log::debug!("open document [{}]", url);
|
||||
homemade_tauri_shell_open(tauri_app_handle.clone(), app_path).await?
|
||||
}
|
||||
OnOpened::Document { url } => {
|
||||
log::debug!("open document [{}]", url);
|
||||
|
||||
homemade_tauri_shell_open(tauri_app_handle.clone(), url).await?
|
||||
}
|
||||
#[cfg(target_os = "macos")]
|
||||
OnOpened::WindowManagementAction { action } => {
|
||||
log::debug!("perform Window Management action [{:?}]", action);
|
||||
homemade_tauri_shell_open(tauri_app_handle.clone(), url).await?
|
||||
}
|
||||
#[cfg(target_os = "macos")]
|
||||
OnOpened::WindowManagementAction { action } => {
|
||||
log::debug!("perform Window Management action [{:?}]", action);
|
||||
|
||||
crate::extension::built_in::window_management::perform_action_on_main_thread(
|
||||
&tauri_app_handle,
|
||||
action,
|
||||
)?;
|
||||
}
|
||||
OnOpened::Extension(ext_on_opened) => {
|
||||
// Apply the settings that would affect open behavior
|
||||
if let Some(settings) = ext_on_opened.settings {
|
||||
if let Some(should_hide) = settings.hide_before_open {
|
||||
if should_hide {
|
||||
crate::hide_coco(tauri_app_handle.clone()).await;
|
||||
crate::extension::built_in::window_management::perform_action_on_main_thread(
|
||||
&tauri_app_handle,
|
||||
action,
|
||||
)?;
|
||||
}
|
||||
OnOpened::Extension(ext_on_opened) => {
|
||||
// Apply the settings that would affect open behavior
|
||||
if let Some(settings) = ext_on_opened.settings {
|
||||
if let Some(should_hide) = settings.hide_before_open {
|
||||
if should_hide {
|
||||
crate::hide_coco(tauri_app_handle.clone()).await;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
let permission = ext_on_opened.permission;
|
||||
let permission = ext_on_opened.permission;
|
||||
|
||||
match ext_on_opened.ty {
|
||||
ExtensionOnOpenedType::Command { action } => {
|
||||
log::debug!("open (execute) command [{:?}]", action);
|
||||
match ext_on_opened.ty {
|
||||
ExtensionOnOpenedType::Command { action } => {
|
||||
log::debug!("open (execute) command [{:?}]", action);
|
||||
|
||||
let mut cmd = Command::new(action.exec);
|
||||
if let Some(args) = action.args {
|
||||
cmd.args(args);
|
||||
}
|
||||
let output = cmd.output().map_err(|e| e.to_string())?;
|
||||
// Sometimes, we wanna see the result in logs even though it doesn't fail.
|
||||
log::debug!(
|
||||
"executing open(Command) result, exit code: [{}], stdout: [{}], stderr: [{}]",
|
||||
output.status,
|
||||
String::from_utf8_lossy(&output.stdout),
|
||||
String::from_utf8_lossy(&output.stderr)
|
||||
);
|
||||
if !output.status.success() {
|
||||
log::warn!(
|
||||
"executing open(Command) failed, exit code: [{}], stdout: [{}], stderr: [{}]",
|
||||
let mut cmd = Command::new(action.exec);
|
||||
if let Some(args) = action.args {
|
||||
cmd.args(args);
|
||||
}
|
||||
let output = cmd.output().await.map_err(|e| e.to_string())?;
|
||||
// Sometimes, we wanna see the result in logs even though it doesn't fail.
|
||||
log::debug!(
|
||||
"executing open(Command) result, exit code: [{}], stdout: [{}], stderr: [{}]",
|
||||
output.status,
|
||||
String::from_utf8_lossy(&output.stdout),
|
||||
String::from_utf8_lossy(&output.stderr)
|
||||
);
|
||||
|
||||
return Err(format!(
|
||||
"Command failed, stderr [{}]",
|
||||
String::from_utf8_lossy(&output.stderr)
|
||||
));
|
||||
}
|
||||
}
|
||||
ExtensionOnOpenedType::Quicklink {
|
||||
link,
|
||||
open_with: opt_open_with,
|
||||
} => {
|
||||
let url = link.concatenate_url(&extra_args);
|
||||
|
||||
log::debug!("open quicklink [{}] with [{:?}]", url, opt_open_with);
|
||||
|
||||
cfg_if::cfg_if! {
|
||||
// The `open_with` functionality is only supported on macOS, provided
|
||||
// by the `open -a` command.
|
||||
if #[cfg(target_os = "macos")] {
|
||||
let mut cmd = Command::new("open");
|
||||
if let Some(ref open_with) = opt_open_with {
|
||||
cmd.arg("-a");
|
||||
cmd.arg(open_with.as_str());
|
||||
}
|
||||
cmd.arg(&url);
|
||||
|
||||
let output = cmd.output().map_err(|e| format!("failed to spawn [open] due to error [{}]", e))?;
|
||||
|
||||
if !output.status.success() {
|
||||
return Err(format!(
|
||||
"failed to open with app {:?}: {}",
|
||||
opt_open_with,
|
||||
if !output.status.success() {
|
||||
log::warn!(
|
||||
"executing open(Command) failed, exit code: [{}], stdout: [{}], stderr: [{}]",
|
||||
output.status,
|
||||
String::from_utf8_lossy(&output.stdout),
|
||||
String::from_utf8_lossy(&output.stderr)
|
||||
));
|
||||
}
|
||||
} else {
|
||||
homemade_tauri_shell_open(tauri_app_handle.clone(), url).await?
|
||||
);
|
||||
|
||||
return Err(format!(
|
||||
"Command failed, stderr [{}]",
|
||||
String::from_utf8_lossy(&output.stderr)
|
||||
));
|
||||
}
|
||||
}
|
||||
}
|
||||
ExtensionOnOpenedType::View {
|
||||
name,
|
||||
icon,
|
||||
page,
|
||||
ui,
|
||||
} => {
|
||||
let page_path = Utf8Path::new(&page);
|
||||
let directory = page_path.parent().unwrap_or_else(|| {
|
||||
panic!("View extension page path should have a parent, i.e., it should be under a directory, but [{}] does not", page);
|
||||
});
|
||||
let mut url = serve_files_in(directory.as_ref()).await;
|
||||
ExtensionOnOpenedType::Quicklink {
|
||||
link,
|
||||
open_with: opt_open_with,
|
||||
} => {
|
||||
let url = link.concatenate_url(&extra_args);
|
||||
|
||||
/*
|
||||
* Emit an event to let the frontend code open this extension.
|
||||
*
|
||||
* Payload `view_extension_opened` contains the information needed
|
||||
* to do that.
|
||||
*
|
||||
* See "src/pages/main/index.tsx" for more info.
|
||||
*/
|
||||
use camino::Utf8Path;
|
||||
use serde_json::Value as Json;
|
||||
use serde_json::to_value;
|
||||
log::debug!("open quicklink [{}] with [{:?}]", url, opt_open_with);
|
||||
|
||||
let html_filename = page_path
|
||||
.file_name()
|
||||
.unwrap_or_else(|| {
|
||||
panic!("View extension page path should have a file name, but [{}] does not have one", page);
|
||||
}).to_string();
|
||||
url.push('/');
|
||||
url.push_str(&html_filename);
|
||||
cfg_if::cfg_if! {
|
||||
// The `open_with` functionality is only supported on macOS, provided
|
||||
// by the `open -a` command.
|
||||
if #[cfg(target_os = "macos")] {
|
||||
let mut cmd = Command::new("open");
|
||||
if let Some(ref open_with) = opt_open_with {
|
||||
cmd.arg("-a");
|
||||
cmd.arg(open_with.as_str());
|
||||
}
|
||||
cmd.arg(&url);
|
||||
|
||||
let html_file_url = url;
|
||||
debug!("View extension listening on: {}", html_file_url);
|
||||
let view_extension_opened: [Json; 5] = [
|
||||
Json::String(name),
|
||||
Json::String(icon),
|
||||
Json::String(html_file_url),
|
||||
to_value(permission).unwrap(),
|
||||
to_value(ui).unwrap(),
|
||||
];
|
||||
tauri_app_handle
|
||||
.emit("open_view_extension", view_extension_opened)
|
||||
.unwrap();
|
||||
let output = cmd.output().await.map_err(|e| format!("failed to spawn [open] due to error [{}]", e))?;
|
||||
|
||||
if !output.status.success() {
|
||||
return Err(format!(
|
||||
"failed to open with app {:?}: {}",
|
||||
opt_open_with,
|
||||
String::from_utf8_lossy(&output.stderr)
|
||||
));
|
||||
}
|
||||
} else {
|
||||
homemade_tauri_shell_open(tauri_app_handle.clone(), url).await?
|
||||
}
|
||||
}
|
||||
}
|
||||
ExtensionOnOpenedType::View {
|
||||
name,
|
||||
icon,
|
||||
page,
|
||||
ui,
|
||||
} => {
|
||||
let page_path = Utf8Path::new(&page);
|
||||
let directory = page_path.parent().unwrap_or_else(|| {
|
||||
panic!("View extension page path should have a parent, i.e., it should be under a directory, but [{}] does not", page);
|
||||
});
|
||||
let mut url = serve_files_in(directory.as_ref()).await;
|
||||
|
||||
/*
|
||||
* Emit an event to let the frontend code open this extension.
|
||||
*
|
||||
* Payload `view_extension_opened` contains the information needed
|
||||
* to do that.
|
||||
*
|
||||
* See "src/pages/main/index.tsx" for more info.
|
||||
*/
|
||||
use camino::Utf8Path;
|
||||
use serde_json::Value as Json;
|
||||
use serde_json::to_value;
|
||||
|
||||
let html_filename = page_path
|
||||
.file_name()
|
||||
.unwrap_or_else(|| {
|
||||
panic!("View extension page path should have a file name, but [{}] does not have one", page);
|
||||
}).to_string();
|
||||
url.push('/');
|
||||
url.push_str(&html_filename);
|
||||
|
||||
let html_file_url = url;
|
||||
debug!("View extension listening on: {}", html_file_url);
|
||||
let view_extension_opened: [Json; 5] = [
|
||||
Json::String(name),
|
||||
Json::String(icon),
|
||||
Json::String(html_file_url),
|
||||
to_value(permission).unwrap(),
|
||||
to_value(ui).unwrap(),
|
||||
];
|
||||
tauri_app_handle
|
||||
.emit("open_view_extension", view_extension_opened)
|
||||
.unwrap();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Ok(())
|
||||
Ok(())
|
||||
};
|
||||
|
||||
match timeout(Duration::from_millis(500), async_closure).await {
|
||||
Ok(res) => res,
|
||||
Err(_timed_out) => {
|
||||
log::warn!("executing open(on_opened: [{:?}]) timed out", on_opened);
|
||||
|
||||
Err(format!(
|
||||
"executing open(on_opened: {:?}) timed out",
|
||||
on_opened
|
||||
))
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Debug, Clone, Serialize, Deserialize, Default)]
|
||||
|
||||
Reference in New Issue
Block a user