|
|
@ -9,7 +9,7 @@ use tauri::{
|
|
|
|
ipc::{CommandScope, GlobalScope},
|
|
|
|
ipc::{CommandScope, GlobalScope},
|
|
|
|
path::BaseDirectory,
|
|
|
|
path::BaseDirectory,
|
|
|
|
utils::config::FsScope,
|
|
|
|
utils::config::FsScope,
|
|
|
|
AppHandle, Manager, Resource, ResourceId, Runtime, Webview,
|
|
|
|
Manager, Resource, ResourceId, Runtime, Webview,
|
|
|
|
};
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
|
|
use std::{
|
|
|
|
use std::{
|
|
|
@ -804,10 +804,34 @@ fn write_file_inner<R: Runtime>(
|
|
|
|
webview: Webview<R>,
|
|
|
|
webview: Webview<R>,
|
|
|
|
global_scope: &GlobalScope<Entry>,
|
|
|
|
global_scope: &GlobalScope<Entry>,
|
|
|
|
command_scope: &CommandScope<Entry>,
|
|
|
|
command_scope: &CommandScope<Entry>,
|
|
|
|
path: SafeFilePath,
|
|
|
|
request: tauri::ipc::Request<'_>,
|
|
|
|
data: &[u8],
|
|
|
|
|
|
|
|
options: Option<WriteFileOptions>,
|
|
|
|
|
|
|
|
) -> CommandResult<()> {
|
|
|
|
) -> CommandResult<()> {
|
|
|
|
|
|
|
|
let data = match request.body() {
|
|
|
|
|
|
|
|
tauri::ipc::InvokeBody::Raw(data) => Cow::Borrowed(data),
|
|
|
|
|
|
|
|
tauri::ipc::InvokeBody::Json(serde_json::Value::Array(data)) => Cow::Owned(
|
|
|
|
|
|
|
|
data.iter()
|
|
|
|
|
|
|
|
.flat_map(|v| v.as_number().and_then(|v| v.as_u64().map(|v| v as u8)))
|
|
|
|
|
|
|
|
.collect(),
|
|
|
|
|
|
|
|
),
|
|
|
|
|
|
|
|
_ => return Err(anyhow::anyhow!("unexpected invoke body").into()),
|
|
|
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
let path = request
|
|
|
|
|
|
|
|
.headers()
|
|
|
|
|
|
|
|
.get("path")
|
|
|
|
|
|
|
|
.ok_or_else(|| anyhow::anyhow!("missing file path").into())
|
|
|
|
|
|
|
|
.and_then(|p| {
|
|
|
|
|
|
|
|
percent_encoding::percent_decode(p.as_ref())
|
|
|
|
|
|
|
|
.decode_utf8()
|
|
|
|
|
|
|
|
.map_err(|_| anyhow::anyhow!("path is not a valid UTF-8").into())
|
|
|
|
|
|
|
|
})
|
|
|
|
|
|
|
|
.and_then(|p| SafeFilePath::from_str(&p).map_err(CommandError::from))?;
|
|
|
|
|
|
|
|
let options: Option<WriteFileOptions> = request
|
|
|
|
|
|
|
|
.headers()
|
|
|
|
|
|
|
|
.get("options")
|
|
|
|
|
|
|
|
.and_then(|p| p.to_str().ok())
|
|
|
|
|
|
|
|
.and_then(|opts| serde_json::from_str(opts).ok());
|
|
|
|
|
|
|
|
|
|
|
|
let (mut file, path) = resolve_file(
|
|
|
|
let (mut file, path) = resolve_file(
|
|
|
|
&webview,
|
|
|
|
&webview,
|
|
|
|
global_scope,
|
|
|
|
global_scope,
|
|
|
@ -844,7 +868,7 @@ fn write_file_inner<R: Runtime>(
|
|
|
|
},
|
|
|
|
},
|
|
|
|
)?;
|
|
|
|
)?;
|
|
|
|
|
|
|
|
|
|
|
|
file.write_all(data)
|
|
|
|
file.write_all(&data)
|
|
|
|
.map_err(|e| {
|
|
|
|
.map_err(|e| {
|
|
|
|
format!(
|
|
|
|
format!(
|
|
|
|
"failed to write bytes to file at path: {} with error: {e}",
|
|
|
|
"failed to write bytes to file at path: {} with error: {e}",
|
|
|
@ -861,52 +885,18 @@ pub async fn write_file<R: Runtime>(
|
|
|
|
command_scope: CommandScope<Entry>,
|
|
|
|
command_scope: CommandScope<Entry>,
|
|
|
|
request: tauri::ipc::Request<'_>,
|
|
|
|
request: tauri::ipc::Request<'_>,
|
|
|
|
) -> CommandResult<()> {
|
|
|
|
) -> CommandResult<()> {
|
|
|
|
let data = match request.body() {
|
|
|
|
write_file_inner(webview, &global_scope, &command_scope, request)
|
|
|
|
tauri::ipc::InvokeBody::Raw(data) => Cow::Borrowed(data),
|
|
|
|
|
|
|
|
tauri::ipc::InvokeBody::Json(serde_json::Value::Array(data)) => Cow::Owned(
|
|
|
|
|
|
|
|
data.iter()
|
|
|
|
|
|
|
|
.flat_map(|v| v.as_number().and_then(|v| v.as_u64().map(|v| v as u8)))
|
|
|
|
|
|
|
|
.collect(),
|
|
|
|
|
|
|
|
),
|
|
|
|
|
|
|
|
_ => return Err(anyhow::anyhow!("unexpected invoke body").into()),
|
|
|
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
let path = request
|
|
|
|
|
|
|
|
.headers()
|
|
|
|
|
|
|
|
.get("path")
|
|
|
|
|
|
|
|
.ok_or_else(|| anyhow::anyhow!("missing file path").into())
|
|
|
|
|
|
|
|
.and_then(|p| {
|
|
|
|
|
|
|
|
percent_encoding::percent_decode(p.as_ref())
|
|
|
|
|
|
|
|
.decode_utf8()
|
|
|
|
|
|
|
|
.map_err(|_| anyhow::anyhow!("path is not a valid UTF-8").into())
|
|
|
|
|
|
|
|
})
|
|
|
|
|
|
|
|
.and_then(|p| SafeFilePath::from_str(&p).map_err(CommandError::from))?;
|
|
|
|
|
|
|
|
let options = request
|
|
|
|
|
|
|
|
.headers()
|
|
|
|
|
|
|
|
.get("options")
|
|
|
|
|
|
|
|
.and_then(|p| p.to_str().ok())
|
|
|
|
|
|
|
|
.and_then(|opts| serde_json::from_str(opts).ok());
|
|
|
|
|
|
|
|
write_file_inner(webview, &global_scope, &command_scope, path, &data, options)
|
|
|
|
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
// TODO, in v3, remove this command and rely on `write_file` command only
|
|
|
|
#[tauri::command]
|
|
|
|
#[tauri::command]
|
|
|
|
pub async fn write_text_file<R: Runtime>(
|
|
|
|
pub async fn write_text_file<R: Runtime>(
|
|
|
|
#[allow(unused)] app: AppHandle<R>,
|
|
|
|
webview: Webview<R>,
|
|
|
|
#[allow(unused)] webview: Webview<R>,
|
|
|
|
global_scope: GlobalScope<Entry>,
|
|
|
|
#[allow(unused)] global_scope: GlobalScope<Entry>,
|
|
|
|
command_scope: CommandScope<Entry>,
|
|
|
|
#[allow(unused)] command_scope: CommandScope<Entry>,
|
|
|
|
request: tauri::ipc::Request<'_>,
|
|
|
|
path: SafeFilePath,
|
|
|
|
|
|
|
|
data: String,
|
|
|
|
|
|
|
|
#[allow(unused)] options: Option<WriteFileOptions>,
|
|
|
|
|
|
|
|
) -> CommandResult<()> {
|
|
|
|
) -> CommandResult<()> {
|
|
|
|
write_file_inner(
|
|
|
|
write_file_inner(webview, &global_scope, &command_scope, request)
|
|
|
|
webview,
|
|
|
|
|
|
|
|
&global_scope,
|
|
|
|
|
|
|
|
&command_scope,
|
|
|
|
|
|
|
|
path,
|
|
|
|
|
|
|
|
data.as_bytes(),
|
|
|
|
|
|
|
|
options,
|
|
|
|
|
|
|
|
)
|
|
|
|
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
#[tauri::command]
|
|
|
|
#[tauri::command]
|
|
|
|