mirror of
https://github.com/tauri-apps/tauri.git
synced 2024-11-11 17:09:16 +03:00
feat(api/shell): allow open command to open files (#1341)
This commit is contained in:
parent
e996e1bcbd
commit
7c0bf642a9
@ -7,7 +7,7 @@ import { invokeTauriCommand } from './helpers/tauri'
|
||||
* @param [args] command args
|
||||
* @return promise resolving to the stdout text
|
||||
*/
|
||||
async function execute(
|
||||
async function execute (
|
||||
command: string,
|
||||
args?: string | string[]
|
||||
): Promise<string> {
|
||||
@ -26,16 +26,19 @@ async function execute(
|
||||
}
|
||||
|
||||
/**
|
||||
* opens an URL on the user default browser
|
||||
* opens a path or URL with the system's default app,
|
||||
* or the one specified with `openWith`
|
||||
*
|
||||
* @param url the URL to open
|
||||
* @param path the path or URL to open
|
||||
* @param openWith the app to open the file or URL with
|
||||
*/
|
||||
async function open(url: string): Promise<void> {
|
||||
async function open (path: string, openWith?: string): Promise<void> {
|
||||
return invokeTauriCommand({
|
||||
__tauriModule: 'Shell',
|
||||
message: {
|
||||
cmd: 'open',
|
||||
uri: url
|
||||
path,
|
||||
with: openWith
|
||||
}
|
||||
})
|
||||
}
|
||||
|
@ -37,6 +37,7 @@ clap = { version = "=3.0.0-beta.2", optional = true }
|
||||
notify-rust = { version = "4.3.0", optional = true }
|
||||
once_cell = "1.7.2"
|
||||
tauri-hotkey = { git = "https://github.com/tauri-apps/tauri-hotkey-rs", branch = "dev", optional = true }
|
||||
open = "1.5.1"
|
||||
|
||||
[dev-dependencies]
|
||||
quickcheck = "1.0.3"
|
||||
|
@ -61,4 +61,7 @@ pub enum Error {
|
||||
#[cfg(feature = "global-shortcut")]
|
||||
#[error("shortcut error: {0}")]
|
||||
Shortcut(#[from] tauri_hotkey::Error),
|
||||
/// Shell error.
|
||||
#[error("shell error: {0}")]
|
||||
Shell(String),
|
||||
}
|
||||
|
@ -15,6 +15,8 @@ pub mod http;
|
||||
pub mod path;
|
||||
/// The RPC module includes utilities to send messages to the JS layer of the webview.
|
||||
pub mod rpc;
|
||||
/// The shell api.
|
||||
pub mod shell;
|
||||
/// TCP ports access API.
|
||||
pub mod tcp;
|
||||
/// The semver API.
|
||||
|
23
tauri-api/src/shell.rs
Normal file
23
tauri-api/src/shell.rs
Normal file
@ -0,0 +1,23 @@
|
||||
/// Open path or URL with `with`, or system default
|
||||
pub fn open(path: String, with: Option<String>) -> crate::Result<()> {
|
||||
{
|
||||
let exit_status = if let Some(with) = with {
|
||||
open::with(&path, &with)
|
||||
} else {
|
||||
open::that(&path)
|
||||
};
|
||||
match exit_status {
|
||||
Ok(status) => {
|
||||
if status.success() {
|
||||
Ok(())
|
||||
} else {
|
||||
Err(crate::Error::Shell("open command failed".into()))
|
||||
}
|
||||
}
|
||||
Err(err) => Err(crate::Error::Shell(format!(
|
||||
"failed to open: {}",
|
||||
err.to_string()
|
||||
))),
|
||||
}
|
||||
}
|
||||
}
|
@ -21,7 +21,6 @@ features = [ "api-all" ]
|
||||
serde_json = "1.0"
|
||||
serde = { version = "1.0", features = [ "derive" ] }
|
||||
base64 = "0.13.0"
|
||||
webbrowser = "0.5.5"
|
||||
lazy_static = "1.4.0"
|
||||
tokio = { version = "1.2", features = ["rt", "rt-multi-thread", "sync"] }
|
||||
futures = "0.3"
|
||||
|
39
tauri/examples/api/src-tauri/Cargo.lock
generated
39
tauri/examples/api/src-tauri/Cargo.lock
generated
@ -1,5 +1,7 @@
|
||||
# This file is automatically @generated by Cargo.
|
||||
# It is not intended for manual editing.
|
||||
version = 3
|
||||
|
||||
[[package]]
|
||||
name = "ab_glyph_rasterizer"
|
||||
version = "0.1.4"
|
||||
@ -1855,9 +1857,19 @@ dependencies = [
|
||||
|
||||
[[package]]
|
||||
name = "once_cell"
|
||||
version = "1.7.0"
|
||||
version = "1.7.2"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "10acf907b94fc1b1a152d08ef97e7759650268cf986bf127f387e602b02c7e5a"
|
||||
checksum = "af8b08b04175473088b46763e51ee54da5f9a164bc162f615b91bc179dbf15a3"
|
||||
|
||||
[[package]]
|
||||
name = "open"
|
||||
version = "1.5.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "b2033f93630dd4b04768ecf5e16bcd3002a89e1e1dbef375bf290dd67e2b7a4d"
|
||||
dependencies = [
|
||||
"which",
|
||||
"winapi 0.3.9",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "openssl"
|
||||
@ -2766,7 +2778,6 @@ dependencies = [
|
||||
"thiserror",
|
||||
"tokio",
|
||||
"uuid",
|
||||
"webbrowser",
|
||||
"wry",
|
||||
]
|
||||
|
||||
@ -2782,6 +2793,7 @@ dependencies = [
|
||||
"http",
|
||||
"notify-rust",
|
||||
"once_cell",
|
||||
"open",
|
||||
"rand 0.8.3",
|
||||
"reqwest",
|
||||
"rfd",
|
||||
@ -3337,17 +3349,6 @@ dependencies = [
|
||||
"wasm-bindgen",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "webbrowser"
|
||||
version = "0.5.5"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "ecad156490d6b620308ed411cfee90d280b3cbd13e189ea0d3fada8acc89158a"
|
||||
dependencies = [
|
||||
"web-sys",
|
||||
"widestring",
|
||||
"winapi 0.3.9",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "webkit2gtk"
|
||||
version = "0.11.0"
|
||||
@ -3430,6 +3431,16 @@ dependencies = [
|
||||
"cc",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "which"
|
||||
version = "4.0.2"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "87c14ef7e1b8b8ecfc75d5eca37949410046e66f15d185c01d70824f1f8111ef"
|
||||
dependencies = [
|
||||
"libc",
|
||||
"thiserror",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "widestring"
|
||||
version = "0.4.3"
|
||||
|
@ -26,7 +26,9 @@
|
||||
setIcon
|
||||
} = appWindow
|
||||
|
||||
let urlValue = "https://tauri.studio";
|
||||
export let onMessage;
|
||||
let pathValue = "https://tauri.studio";
|
||||
let openWith = "";
|
||||
let resizable = true
|
||||
let maximized = false
|
||||
let decorations = false
|
||||
@ -44,7 +46,7 @@
|
||||
let windowTitle = 'Awesome Tauri Example!';
|
||||
|
||||
function openUrl() {
|
||||
open(urlValue);
|
||||
open(pathValue, !!openWith ? openWith : undefined).catch(onMessage);
|
||||
}
|
||||
|
||||
function setTitle_() {
|
||||
@ -188,8 +190,15 @@
|
||||
<button class="button" type="submit">Set title</button>
|
||||
</form>
|
||||
<form style="margin-top: 24px" on:submit|preventDefault={openUrl}>
|
||||
<input id="url" bind:value={urlValue} />
|
||||
<button class="button" id="open-url">
|
||||
Open URL
|
||||
<div>
|
||||
<label for="path">Path or URL:</label>
|
||||
<input id="path" bind:value={pathValue} />
|
||||
</div>
|
||||
<div>
|
||||
<label for="openWith">Open With (Optional):</label>
|
||||
<input id="openWith" bind:value={openWith} />
|
||||
</div>
|
||||
<button class="button" id="open-path">
|
||||
Open Path or Url
|
||||
</button>
|
||||
</form>
|
@ -6,9 +6,14 @@ use serde::Deserialize;
|
||||
#[serde(tag = "cmd", rename_all = "camelCase")]
|
||||
pub enum Cmd {
|
||||
/// The execute script API.
|
||||
Execute { command: String, args: Vec<String> },
|
||||
/// The open URL in browser API
|
||||
Open { uri: String },
|
||||
Execute {
|
||||
command: String,
|
||||
args: Vec<String>,
|
||||
},
|
||||
Open {
|
||||
path: String,
|
||||
with: Option<String>,
|
||||
},
|
||||
}
|
||||
|
||||
impl Cmd {
|
||||
@ -28,37 +33,16 @@ impl Cmd {
|
||||
"shell > execute".to_string(),
|
||||
))
|
||||
}
|
||||
Self::Open { uri } => {
|
||||
Self::Open { path, with } => {
|
||||
#[cfg(shell_open)]
|
||||
{
|
||||
open_browser(uri);
|
||||
Ok(().into())
|
||||
match crate::api::shell::open(path, with) {
|
||||
Ok(_) => Ok(().into()),
|
||||
Err(err) => Err(crate::Error::FailedToExecuteApi(err)),
|
||||
}
|
||||
|
||||
#[cfg(not(shell_open))]
|
||||
Err(crate::Error::ApiNotAllowlisted("shell > open".to_string()))
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(shell_open)]
|
||||
pub fn open_browser(uri: String) {
|
||||
#[cfg(test)]
|
||||
assert!(uri.contains("http://"));
|
||||
|
||||
#[cfg(not(test))]
|
||||
webbrowser::open(&uri).expect("Failed to open webbrowser with uri");
|
||||
}
|
||||
|
||||
#[cfg(test)]
|
||||
mod test {
|
||||
use proptest::prelude::*;
|
||||
// Test the open func to see if proper uris can be opened by the browser.
|
||||
proptest! {
|
||||
#[cfg(shell_open)]
|
||||
#[test]
|
||||
fn check_open(uri in r"(http://)([\\w\\d\\.]+([\\w]{2,6})?)") {
|
||||
super::open_browser(uri);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user