chore: edition 2024

This commit is contained in:
Lucas Nogueira
2026-09-26 15:36:22 -03:00
parent b517cc7e85
commit 3d8a3c877b
100 changed files with 276 additions and 253 deletions
+2 -3
View File
@@ -11,11 +11,10 @@
#![cfg(not(any(target_os = "android", target_os = "ios")))]
use auto_launch::{AutoLaunch, AutoLaunchBuilder};
use serde::{ser::Serializer, Serialize};
use serde::{Serialize, ser::Serializer};
use tauri::{
command,
Manager, Runtime, State, command,
plugin::{Builder as PluginBuilder, TauriPlugin},
Manager, Runtime, State,
};
use std::env::current_exe;
+1 -1
View File
@@ -2,7 +2,7 @@
// SPDX-License-Identifier: Apache-2.0
// SPDX-License-Identifier: MIT
use serde::{ser::Serializer, Serialize};
use serde::{Serialize, ser::Serializer};
/// Alias for the result type returned by this crate's functions.
pub type Result<T> = std::result::Result<T, Error>;
+1 -1
View File
@@ -9,8 +9,8 @@
#![cfg(mobile)]
use tauri::{
plugin::{Builder, PluginHandle, TauriPlugin},
Manager, Runtime,
plugin::{Builder, PluginHandle, TauriPlugin},
};
pub use models::*;
+1 -1
View File
@@ -2,7 +2,7 @@
// SPDX-License-Identifier: Apache-2.0
// SPDX-License-Identifier: MIT
use serde::{ser::Serializer, Serialize};
use serde::{Serialize, ser::Serializer};
/// Alias for a [`Result`](std::result::Result) with the error type [`Error`].
pub type Result<T> = std::result::Result<T, Error>;
+1 -1
View File
@@ -10,8 +10,8 @@
use serde::Serialize;
use tauri::{
plugin::{Builder, PluginHandle, TauriPlugin},
Manager, Runtime,
plugin::{Builder, PluginHandle, TauriPlugin},
};
pub use models::*;
+1 -1
View File
@@ -12,8 +12,8 @@
)]
use tauri::{
plugin::{Builder, PluginApi, TauriPlugin},
AppHandle, Manager, Runtime, State,
plugin::{Builder, PluginApi, TauriPlugin},
};
mod config;
+3 -4
View File
@@ -3,9 +3,9 @@
// SPDX-License-Identifier: MIT
use clap::{
Arg as ClapArg, ArgAction, ArgMatches, Command,
builder::{PossibleValue, PossibleValuesParser},
error::ErrorKind,
Arg as ClapArg, ArgAction, ArgMatches, Command,
};
use serde::Serialize;
use serde_json::Value;
@@ -134,8 +134,8 @@ fn get_matches_internal(config: &Config, matches: &ArgMatches) -> Matches {
let mut cli_matches = Matches::default();
map_matches(config, matches, &mut cli_matches);
if let Some((subcommand_name, subcommand_matches)) = matches.subcommand() {
if let Some(subcommand_config) = config
if let Some((subcommand_name, subcommand_matches)) = matches.subcommand()
&& let Some(subcommand_config) = config
.subcommands
.as_ref()
.and_then(|s| s.get(subcommand_name))
@@ -145,7 +145,6 @@ fn get_matches_internal(config: &Config, matches: &ArgMatches) -> Matches {
get_matches_internal(subcommand_config, subcommand_matches),
);
}
}
cli_matches
}
+1 -1
View File
@@ -2,7 +2,7 @@
// SPDX-License-Identifier: Apache-2.0
// SPDX-License-Identifier: MIT
use tauri::{command, image::JsImage, AppHandle, Manager, ResourceId, Runtime, State, Webview};
use tauri::{AppHandle, Manager, ResourceId, Runtime, State, Webview, command, image::JsImage};
use crate::{Clipboard, Result};
+1 -1
View File
@@ -4,7 +4,7 @@
use arboard::ImageData;
use serde::de::DeserializeOwned;
use tauri::{image::Image, plugin::PluginApi, AppHandle, Runtime};
use tauri::{AppHandle, Runtime, image::Image, plugin::PluginApi};
use std::{borrow::Cow, sync::Mutex};
+1 -1
View File
@@ -2,7 +2,7 @@
// SPDX-License-Identifier: Apache-2.0
// SPDX-License-Identifier: MIT
use serde::{ser::Serializer, Serialize};
use serde::{Serialize, ser::Serializer};
/// Alias for `Result<T, Error>` used throughout this crate.
pub type Result<T> = std::result::Result<T, Error>;
+1 -1
View File
@@ -10,8 +10,8 @@
)]
use tauri::{
plugin::{Builder, TauriPlugin},
Manager, RunEvent, Runtime,
plugin::{Builder, TauriPlugin},
};
#[cfg(desktop)]
+1 -1
View File
@@ -5,9 +5,9 @@
use serde::de::DeserializeOwned;
use serde::{Deserialize, Serialize};
use tauri::{
AppHandle, Runtime,
image::Image,
plugin::{PluginApi, PluginHandle},
AppHandle, Runtime,
};
use std::borrow::Cow;
@@ -5,7 +5,7 @@ description = "A Tauri App"
authors = ["you"]
license = ""
repository = ""
edition = "2021"
edition = "2024"
rust-version = "1.90"
# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html
+1 -1
View File
@@ -2,7 +2,7 @@
// SPDX-License-Identifier: Apache-2.0
// SPDX-License-Identifier: MIT
use tauri::{command, AppHandle, Runtime, State, Window};
use tauri::{AppHandle, Runtime, State, Window, command};
use crate::{DeepLink, Result};
+5 -4
View File
@@ -50,7 +50,9 @@ impl AssociatedDomain {
}
if self.scheme.iter().any(|s| s == "http") && !self.scheme.iter().any(|s| s == "https")
{
eprintln!("Warning: AppLink uses only 'http' — allowed on Android but not secure for production.");
eprintln!(
"Warning: AppLink uses only 'http' — allowed on Android but not secure for production."
);
}
}
@@ -68,13 +70,12 @@ where
D: Deserializer<'de>,
{
let opt = Option::<String>::deserialize(deserializer)?;
if let Some(ref host) = opt {
if let Some((scheme, _)) = host.split_once("://") {
if let Some(ref host) = opt
&& let Some((scheme, _)) = host.split_once("://") {
return Err(serde::de::Error::custom(format!(
"host `{host}` cannot start with a scheme, please remove the `{scheme}://` prefix"
)));
}
}
Ok(opt)
}
+1 -1
View File
@@ -2,7 +2,7 @@
// SPDX-License-Identifier: Apache-2.0
// SPDX-License-Identifier: MIT
use serde::{ser::Serializer, Serialize};
use serde::{Serialize, ser::Serializer};
/// Alias for a [`Result`](std::result::Result) with the error type [`Error`].
pub type Result<T> = std::result::Result<T, Error>;
+13 -12
View File
@@ -11,8 +11,8 @@
//! calling those methods returns [`Error::UnsupportedPlatform`].
use tauri::{
plugin::{Builder, PluginApi, TauriPlugin},
AppHandle, EventId, Listener, Manager, Runtime,
plugin::{Builder, PluginApi, TauriPlugin},
};
mod commands;
@@ -33,8 +33,8 @@ fn init_deep_link<R: Runtime>(
let _api = api;
use tauri::{
ipc::{Channel, InvokeResponseBody},
Emitter,
ipc::{Channel, InvokeResponseBody},
};
let handle = _api.register_android_plugin(PLUGIN_IDENTIFIER, "DeepLinkPlugin")?;
@@ -94,7 +94,7 @@ fn init_deep_link<R: Runtime>(
#[cfg(target_os = "android")]
mod imp {
use tauri::{ipc::Channel, plugin::PluginHandle, AppHandle, Runtime};
use tauri::{AppHandle, Runtime, ipc::Channel, plugin::PluginHandle};
use serde::{Deserialize, Serialize};
@@ -172,7 +172,7 @@ mod imp {
use std::sync::Mutex;
#[cfg(target_os = "linux")]
use std::{
fs::{create_dir_all, File},
fs::{File, create_dir_all},
io::Write,
process::Command,
};
@@ -223,7 +223,9 @@ mod imp {
current.replace(vec![url.clone()]);
let _ = self.app.emit("deep-link://new-url", vec![url]);
} else if cfg!(debug_assertions) {
tracing::warn!("argument {url} does not match any configured deep link scheme; skipping it");
tracing::warn!(
"argument {url} does not match any configured deep link scheme; skipping it"
);
}
}
}
@@ -414,11 +416,10 @@ mod imp {
let mimeapps_path = self.app.path().config_dir()?.join("mimeapps.list");
if mimeapps_path.exists() {
let mut mimeapps = ini::Ini::load_from_file(&mimeapps_path)?;
if let Some(section) = mimeapps.section_mut(Some("Default Applications")) {
if section.get(&mime_type).unwrap_or_default() == file_name {
if let Some(section) = mimeapps.section_mut(Some("Default Applications"))
&& section.get(&mime_type).unwrap_or_default() == file_name {
section.remove(&mime_type);
}
}
mimeapps.write_to_file(&mimeapps_path)?;
}
@@ -558,16 +559,16 @@ impl<R: Runtime> DeepLink<R> {
///
/// Use `get_current` on app load to check whether your app was started via a deep link.
pub fn on_open_url<F: Fn(OpenUrlEvent) + Send + Sync + 'static>(&self, f: F) -> EventId {
let event_id = self.app.listen("deep-link://new-url", move |event| {
self.app.listen("deep-link://new-url", move |event| {
if let Ok(urls) = serde_json::from_str(event.payload()) {
f(OpenUrlEvent {
id: event.id(),
urls,
})
}
});
event_id
})
}
}
+7 -10
View File
@@ -5,7 +5,7 @@
use std::path::PathBuf;
use serde::{Deserialize, Serialize};
use tauri::{command, Manager, Runtime, State, Window};
use tauri::{Manager, Runtime, State, Window, command};
use tauri_plugin_fs::FsExt;
use crate::{
@@ -171,14 +171,13 @@ pub(crate) async fn open<R: Runtime>(
)
} else {
let folder = dialog_builder.blocking_pick_folder();
if let Some(folder) = &folder {
if let Ok(path) = folder.clone().into_path() {
if let Some(folder) = &folder
&& let Ok(path) = folder.clone().into_path() {
if let Some(s) = window.try_fs_scope() {
s.allow_directory(&path, options.recursive)?;
}
tauri_scope.allow_directory(&path, options.directory)?;
}
}
OpenResponse::Folder(folder.map(|p| p.simplified()))
}
}
@@ -204,14 +203,13 @@ pub(crate) async fn open<R: Runtime>(
let tauri_scope = window.state::<tauri::scope::Scopes>();
let file = dialog_builder.blocking_pick_file();
if let Some(file) = &file {
if let Ok(path) = file.clone().into_path() {
if let Some(file) = &file
&& let Ok(path) = file.clone().into_path() {
if let Some(s) = window.try_fs_scope() {
s.allow_file(&path)?;
}
tauri_scope.allow_file(&path)?;
}
}
OpenResponse::File(file.map(|f| f.simplified()))
};
Ok(res)
@@ -246,14 +244,13 @@ pub(crate) async fn save<R: Runtime>(
let tauri_scope = window.state::<tauri::scope::Scopes>();
let path = dialog_builder.blocking_save_file();
if let Some(p) = &path {
if let Ok(path) = p.clone().into_path() {
if let Some(p) = &path
&& let Ok(path) = p.clone().into_path() {
if let Some(s) = window.try_fs_scope() {
s.allow_file(&path)?;
}
tauri_scope.allow_file(&path)?;
}
}
Ok(path.map(|p| p.simplified()))
}
+2 -2
View File
@@ -11,9 +11,9 @@
use raw_window_handle::{HasDisplayHandle, HasWindowHandle, RawDisplayHandle, RawWindowHandle};
use rfd::{AsyncFileDialog, AsyncMessageDialog};
use serde::de::DeserializeOwned;
use tauri::{plugin::PluginApi, AppHandle, Runtime};
use tauri::{AppHandle, Runtime, plugin::PluginApi};
use crate::{models::*, FileDialogBuilder, FilePath, MessageDialogBuilder};
use crate::{FileDialogBuilder, FilePath, MessageDialogBuilder, models::*};
pub fn init<R: Runtime, C: DeserializeOwned>(
app: &AppHandle<R>,
+1 -1
View File
@@ -2,7 +2,7 @@
// SPDX-License-Identifier: Apache-2.0
// SPDX-License-Identifier: MIT
use serde::{ser::Serializer, Serialize};
use serde::{Serialize, ser::Serializer};
/// Alias for `Result<T, Error>` used throughout this crate.
pub type Result<T> = std::result::Result<T, Error>;
+1 -1
View File
@@ -16,8 +16,8 @@
use serde::{Deserialize, Serialize};
use tauri::{
plugin::{Builder, TauriPlugin},
Manager, Runtime,
plugin::{Builder, TauriPlugin},
};
use std::{
+2 -2
View File
@@ -2,10 +2,10 @@
// SPDX-License-Identifier: Apache-2.0
// SPDX-License-Identifier: MIT
use serde::{de::DeserializeOwned, Deserialize};
use serde::{Deserialize, de::DeserializeOwned};
use tauri::{
plugin::{PluginApi, PluginHandle},
AppHandle, Runtime,
plugin::{PluginApi, PluginHandle},
};
use crate::{FileDialogBuilder, FilePath, MessageDialogBuilder, MessageDialogResult};
+2 -2
View File
@@ -3,9 +3,9 @@
// SPDX-License-Identifier: MIT
use serde::de::DeserializeOwned;
use tauri::{plugin::PluginApi, AppHandle, Runtime};
use tauri::{AppHandle, Runtime, plugin::PluginApi};
use crate::{models::*, FilePath, OpenOptions};
use crate::{FilePath, OpenOptions, models::*};
const PLUGIN_IDENTIFIER: &str = "com.plugin.fs";
+20 -7
View File
@@ -6,10 +6,10 @@
use serde::{Deserialize, Serialize, Serializer};
use serde_repr::{Deserialize_repr, Serialize_repr};
use tauri::{
Manager, Resource, ResourceId, Runtime, Webview,
ipc::{CommandScope, GlobalScope},
path::BaseDirectory,
utils::config::FsScope,
Manager, Resource, ResourceId, Runtime, Webview,
};
use std::{
@@ -23,7 +23,7 @@ use std::{
time::{SystemTime, UNIX_EPOCH},
};
use crate::{scope::Entry, Error, SafeFilePath};
use crate::{Error, SafeFilePath, scope::Entry};
#[derive(Debug, thiserror::Error)]
pub enum CommandError {
@@ -175,7 +175,9 @@ impl<R: Runtime> Drop for FileHandle<R> {
.stop_accessing_security_scoped_resource(FilePath::Url(url.clone()));
security_scoped_resources.remove(url.as_str());
} else {
log::debug!("Not cleaning up security-scoped resource for URL: {url} on drop (manually tracked via start_accessing_security_scoped_resource)");
log::debug!(
"Not cleaning up security-scoped resource for URL: {url} on drop (manually tracked via start_accessing_security_scoped_resource)"
);
}
}
}
@@ -251,7 +253,9 @@ impl<R: Runtime> Drop for PathHandle<R> {
.stop_accessing_security_scoped_resource(FilePath::Url(url.clone()));
security_scoped_resources.remove(url.as_str());
} else {
log::debug!("Not cleaning up security-scoped resource for URL: {url} on drop (manually tracked via start_accessing_security_scoped_resource)");
log::debug!(
"Not cleaning up security-scoped resource for URL: {url} on drop (manually tracked via start_accessing_security_scoped_resource)"
);
}
}
}
@@ -1530,7 +1534,10 @@ pub fn resolve_path<R: Runtime>(
unsafe {
let success = ns_url.startAccessingSecurityScopedResource();
if success {
log::debug!("Started accessing security-scoped resource for URL: {} (via resolve_path)", url.as_str());
log::debug!(
"Started accessing security-scoped resource for URL: {} (via resolve_path)",
url.as_str()
);
// Track it so we know to clean it up
security_scoped_resources.track_manually(url.as_str().to_string());
} else {
@@ -1541,10 +1548,16 @@ pub fn resolve_path<R: Runtime>(
}
}
} else {
log::debug!("Failed to create NSURL from URL: {}, ignoring security-scoped resource access request", url.as_str());
log::debug!(
"Failed to create NSURL from URL: {}, ignoring security-scoped resource access request",
url.as_str()
);
}
} else {
log::debug!("Security-scoped resource already active for URL: {} (started via start_accessing_security_scoped_resource), skipping", url.as_str());
log::debug!(
"Security-scoped resource already active for URL: {} (started via start_accessing_security_scoped_resource), skipping",
url.as_str()
);
}
}
}
+4 -6
View File
@@ -190,11 +190,10 @@ impl<'de> serde::Deserialize<'de> for SafeFilePath {
impl FromStr for FilePath {
type Err = Infallible;
fn from_str(s: &str) -> std::result::Result<Self, Self::Err> {
if let Ok(url) = url::Url::from_str(s) {
if url.scheme().len() != 1 {
if let Ok(url) = url::Url::from_str(s)
&& url.scheme().len() != 1 {
return Ok(Self::Url(url));
}
}
Ok(Self::Path(PathBuf::from(s)))
}
}
@@ -202,11 +201,10 @@ impl FromStr for FilePath {
impl FromStr for SafeFilePath {
type Err = Error;
fn from_str(s: &str) -> Result<Self> {
if let Ok(url) = url::Url::from_str(s) {
if url.scheme().len() != 1 {
if let Ok(url) = url::Url::from_str(s)
&& url.scheme().len() != 1 {
return Ok(Self::Url(url));
}
}
SafePathBuf::new(s.into())
.map(SafeFilePath::Path)
+5 -2
View File
@@ -3,7 +3,7 @@
// SPDX-License-Identifier: MIT
use serde::de::DeserializeOwned;
use tauri::{plugin::PluginApi, AppHandle, Runtime};
use tauri::{AppHandle, Runtime, plugin::PluginApi};
use crate::{FilePath, OpenOptions};
@@ -69,7 +69,10 @@ impl<R: Runtime> Fs<R> {
}
}
} else {
log::debug!("Failed to create NSURL from URL: {}, ignoring security-scoped resource access request", url_string);
log::debug!(
"Failed to create NSURL from URL: {}, ignoring security-scoped resource access request",
url_string
);
}
// Convert URL to path and open the file
+1 -1
View File
@@ -22,10 +22,10 @@ use std::sync::Mutex;
use serde::Deserialize;
use tauri::{
AppHandle, DragDropEvent, Manager, RunEvent, Runtime, WindowEvent,
ipc::ScopeObject,
plugin::{Builder as PluginBuilder, TauriPlugin},
utils::{acl::Value, config::FsScope},
AppHandle, DragDropEvent, Manager, RunEvent, Runtime, WindowEvent,
};
#[cfg(target_os = "android")]
+4 -4
View File
@@ -3,20 +3,20 @@
// SPDX-License-Identifier: MIT
use notify::{Config, RecommendedWatcher, RecursiveMode, Watcher};
use notify_debouncer_full::{new_debouncer, DebouncedEvent, Debouncer, RecommendedCache};
use notify_debouncer_full::{DebouncedEvent, Debouncer, RecommendedCache, new_debouncer};
use serde::Deserialize;
use tauri::{
Manager, Resource, ResourceId, Runtime, Webview,
ipc::{Channel, CommandScope, GlobalScope},
path::BaseDirectory,
Manager, Resource, ResourceId, Runtime, Webview,
};
use std::time::Duration;
use crate::{
commands::{resolve_path, CommandResult},
scope::Entry,
SafeFilePath,
commands::{CommandResult, resolve_path},
scope::Entry,
};
#[allow(unused)]
+1 -1
View File
@@ -2,7 +2,7 @@
// SPDX-License-Identifier: Apache-2.0
// SPDX-License-Identifier: MIT
use tauri::{command, ipc::Channel, AppHandle, Runtime};
use tauri::{AppHandle, Runtime, command, ipc::Channel};
use crate::{GeolocationExt, PermissionStatus, PermissionType, Position, PositionOptions, Result};
+2 -2
View File
@@ -2,11 +2,11 @@
// SPDX-License-Identifier: Apache-2.0
// SPDX-License-Identifier: MIT
use serde::{de::DeserializeOwned, Serialize};
use serde::{Serialize, de::DeserializeOwned};
use tauri::{
AppHandle, Runtime,
ipc::{Channel, InvokeResponseBody},
plugin::PluginApi,
AppHandle, Runtime,
};
use crate::models::*;
+1 -1
View File
@@ -2,7 +2,7 @@
// SPDX-License-Identifier: Apache-2.0
// SPDX-License-Identifier: MIT
use serde::{ser::Serializer, Serialize};
use serde::{Serialize, ser::Serializer};
/// Alias for the result type returned by the geolocation APIs.
pub type Result<T> = std::result::Result<T, Error>;
+1 -1
View File
@@ -9,8 +9,8 @@
//! - **specta**: Add support for [`specta::specta`](https://docs.rs/specta/2.0.0-rc.25/specta/attr.specta.html) on structs like [`PermissionStatus`], [`PositionOptions`].
use tauri::{
plugin::{Builder, TauriPlugin},
Manager, Runtime,
plugin::{Builder, TauriPlugin},
};
pub use models::*;
+2 -2
View File
@@ -2,11 +2,11 @@
// SPDX-License-Identifier: Apache-2.0
// SPDX-License-Identifier: MIT
use serde::{de::DeserializeOwned, Serialize};
use serde::{Serialize, de::DeserializeOwned};
use tauri::{
AppHandle, Runtime,
ipc::{Channel, InvokeResponseBody},
plugin::{PluginApi, PluginHandle},
AppHandle, Runtime,
};
use crate::models::*;
+2 -2
View File
@@ -22,14 +22,14 @@ use std::{
use global_hotkey::GlobalHotKeyEvent;
pub use global_hotkey::{
hotkey::{Code, HotKey as Shortcut, Modifiers},
GlobalHotKeyEvent as ShortcutEvent, HotKeyState as ShortcutState,
hotkey::{Code, HotKey as Shortcut, Modifiers},
};
use serde::Serialize;
use tauri::{
AppHandle, Manager, Runtime, State,
ipc::Channel,
plugin::{Builder as PluginBuilder, TauriPlugin},
AppHandle, Manager, Runtime, State,
};
mod error;
+1 -1
View File
@@ -2,7 +2,7 @@
// SPDX-License-Identifier: Apache-2.0
// SPDX-License-Identifier: MIT
use tauri::{command, AppHandle, Runtime};
use tauri::{AppHandle, Runtime, command};
use crate::{HapticsExt, ImpactFeedbackStyle, NotificationFeedbackType, Result};
+1 -1
View File
@@ -3,7 +3,7 @@
// SPDX-License-Identifier: MIT
use serde::de::DeserializeOwned;
use tauri::{plugin::PluginApi, AppHandle, Runtime};
use tauri::{AppHandle, Runtime, plugin::PluginApi};
use crate::models::*;
+1 -1
View File
@@ -2,7 +2,7 @@
// SPDX-License-Identifier: Apache-2.0
// SPDX-License-Identifier: MIT
use serde::{ser::Serializer, Serialize};
use serde::{Serialize, ser::Serializer};
/// Alias for a [`std::result::Result`] with the error type [`Error`].
pub type Result<T> = std::result::Result<T, Error>;
+1 -1
View File
@@ -9,8 +9,8 @@
//! - **specta**: Add support for [`specta::specta`](https://docs.rs/specta/2.0.0-rc.25/specta/attr.specta.html) on structs like [`ImpactFeedbackStyle`], [`NotificationFeedbackType`].
use tauri::{
plugin::{Builder, TauriPlugin},
Manager, Runtime,
plugin::{Builder, TauriPlugin},
};
pub use models::*;
+2 -2
View File
@@ -2,10 +2,10 @@
// SPDX-License-Identifier: Apache-2.0
// SPDX-License-Identifier: MIT
use serde::{de::DeserializeOwned, Serialize};
use serde::{Serialize, de::DeserializeOwned};
use tauri::{
plugin::{PluginApi, PluginHandle},
AppHandle, Runtime,
plugin::{PluginApi, PluginHandle},
};
use crate::models::*;
+20 -13
View File
@@ -4,20 +4,20 @@
use std::{future::Future, pin::Pin, str::FromStr, sync::Arc, time::Duration};
use http::{header, HeaderMap, HeaderName, HeaderValue, Method, StatusCode};
use reqwest::{redirect::Policy, NoProxy};
use http::{HeaderMap, HeaderName, HeaderValue, Method, StatusCode, header};
use reqwest::{NoProxy, redirect::Policy};
use serde::{Deserialize, Serialize};
use tauri::{
Manager, ResourceId, ResourceTable, Runtime, State, Webview,
async_runtime::Mutex,
command,
ipc::{CommandScope, GlobalScope},
Manager, ResourceId, ResourceTable, Runtime, State, Webview,
};
use tokio::sync::oneshot::{channel, Receiver, Sender};
use tokio::sync::oneshot::{Receiver, Sender, channel};
use crate::{
scope::{Entry, Scope},
Error, Http, Result,
scope::{Entry, Scope},
};
const HTTP_USER_AGENT: &str = concat!(env!("CARGO_PKG_NAME"), "/", env!("CARGO_PKG_VERSION"),);
@@ -257,8 +257,12 @@ pub async fn fetch<R: Runtime>(
if is_unsafe_header(&name) {
#[cfg(debug_assertions)]
{
eprintln!("[\x1b[33mWARNING\x1b[0m] Skipping {name} header as it is a forbidden header per fetch spec https://fetch.spec.whatwg.org/#terminology-headers");
eprintln!("[\x1b[33mWARNING\x1b[0m] if keeping the header is a desired behavior, you can enable `unsafe-headers` feature flag in your Cargo.toml");
eprintln!(
"[\x1b[33mWARNING\x1b[0m] Skipping {name} header as it is a forbidden header per fetch spec https://fetch.spec.whatwg.org/#terminology-headers"
);
eprintln!(
"[\x1b[33mWARNING\x1b[0m] if keeping the header is a desired behavior, you can enable `unsafe-headers` feature flag in your Cargo.toml"
);
}
continue;
}
@@ -294,7 +298,9 @@ pub async fn fetch<R: Runtime>(
{
#[cfg(debug_assertions)]
{
eprintln!("[\x1b[33mWARNING\x1b[0m] using dangerous settings requires `dangerous-settings` feature flag in your Cargo.toml");
eprintln!(
"[\x1b[33mWARNING\x1b[0m] using dangerous settings requires `dangerous-settings` feature flag in your Cargo.toml"
);
}
let _ = danger_config;
return Err(Error::DangerousSettings);
@@ -342,8 +348,8 @@ pub async fn fetch<R: Runtime>(
}
// ensure we have an Origin header set
if cfg!(not(feature = "unsafe-headers")) || !headers.contains_key(header::ORIGIN) {
if let Ok(url) = webview.url() {
if (cfg!(not(feature = "unsafe-headers")) || !headers.contains_key(header::ORIGIN))
&& let Ok(url) = webview.url() {
// The url crate returns OpaqueOrigin for tauri://localhost which serializes to "null"
let origin = if url.scheme() == "tauri" {
"tauri://localhost".to_string()
@@ -352,7 +358,6 @@ pub async fn fetch<R: Runtime>(
};
headers.append(header::ORIGIN, HeaderValue::from_str(&origin)?);
}
}
// In case empty origin is passed, remove it. Some services do not like Origin header
// so this way we can remove it in explicit way. The default behaviour is still to set it
@@ -593,8 +598,10 @@ mod tests {
Some(location) => format!(
"HTTP/1.1 302 Found\r\nLocation: {location}\r\nContent-Length: 0\r\nConnection: close\r\n\r\n"
),
None => "HTTP/1.1 200 OK\r\nContent-Length: 6\r\nConnection: close\r\n\r\nsecret"
.to_string(),
None => {
"HTTP/1.1 200 OK\r\nContent-Length: 6\r\nConnection: close\r\n\r\nsecret"
.to_string()
}
};
let _ = stream.write_all(response.as_bytes());
+1 -1
View File
@@ -61,8 +61,8 @@
pub use reqwest;
use tauri::{
plugin::{Builder, TauriPlugin},
Manager, Runtime,
plugin::{Builder, TauriPlugin},
};
pub use config::Config;
+1 -1
View File
@@ -6,7 +6,7 @@
use std::{
path::PathBuf,
sync::{mpsc::Receiver, Mutex},
sync::{Mutex, mpsc::Receiver},
};
use cookie_store::{CookieStore, RawCookie, RawCookieParseError};
+14 -10
View File
@@ -154,11 +154,13 @@ mod tests {
assert!(scope.is_allowed(&"http://localhost:8080/file.png".parse().unwrap()));
assert!(scope.is_allowed(&"http://localhost:8080/file.png#head".parse().unwrap()));
assert!(scope.is_allowed(&"http://localhost:8080/assets/file.png".parse().unwrap()));
assert!(scope.is_allowed(
&"http://localhost:8080/assets/file.png?width=100&height=200"
.parse()
.unwrap()
));
assert!(
scope.is_allowed(
&"http://localhost:8080/assets/file.png?width=100&height=200"
.parse()
.unwrap()
)
);
assert!(!scope.is_allowed(&"http://localhost:8080/file.jpeg".parse().unwrap()));
}
@@ -172,11 +174,13 @@ mod tests {
assert!(scope.is_allowed(&"http://something.else#tauri".parse().unwrap()));
assert!(scope.is_allowed(&"http://something.else/path/to/file".parse().unwrap()));
assert!(scope.is_allowed(&"http://something.else?rel=tauri".parse().unwrap()));
assert!(scope.is_allowed(
&"http://something.else/path/to/file.mp4?start=500"
.parse()
.unwrap()
));
assert!(
scope.is_allowed(
&"http://something.else/path/to/file.mp4?start=500"
.parse()
.unwrap()
)
);
assert!(!scope.is_allowed(&"https://something.else".parse().unwrap()));
+1 -1
View File
@@ -15,8 +15,8 @@ use std::collections::HashMap;
use http::Uri;
use tauri::{
plugin::{Builder as PluginBuilder, TauriPlugin},
Runtime,
plugin::{Builder as PluginBuilder, TauriPlugin},
};
use tiny_http::{Header, Response as HttpResponse, Server};
+5 -5
View File
@@ -27,12 +27,12 @@ use std::{
iter::FromIterator,
path::{Path, PathBuf},
};
use tauri::{
plugin::{self, TauriPlugin},
Manager, Runtime,
};
use tauri::{AppHandle, Emitter};
use time::{macros::format_description, OffsetDateTime};
use tauri::{
Manager, Runtime,
plugin::{self, TauriPlugin},
};
use time::{OffsetDateTime, macros::format_description};
pub use fern;
pub use log;
+1 -1
View File
@@ -2,7 +2,7 @@
// SPDX-License-Identifier: Apache-2.0
// SPDX-License-Identifier: MIT
use serde::{ser::Serializer, Serialize};
use serde::{Serialize, ser::Serializer};
/// Alias for a [`std::result::Result`] with the error type [`Error`].
pub type Result<T> = std::result::Result<T, Error>;
+1 -1
View File
@@ -14,8 +14,8 @@
use serde::{Deserialize, Serialize};
use tauri::{
plugin::{Builder, PluginHandle, TauriPlugin},
Manager, Runtime,
plugin::{Builder, PluginHandle, TauriPlugin},
};
pub use models::*;
+1 -1
View File
@@ -2,7 +2,7 @@
// SPDX-License-Identifier: Apache-2.0
// SPDX-License-Identifier: MIT
use tauri::{command, plugin::PermissionState, AppHandle, Runtime, State};
use tauri::{AppHandle, Runtime, State, command, plugin::PermissionState};
use crate::{Notification, NotificationData, Result};
+1 -1
View File
@@ -4,8 +4,8 @@
use serde::de::DeserializeOwned;
use tauri::{
plugin::{PermissionState, PluginApi},
AppHandle, Runtime,
plugin::{PermissionState, PluginApi},
};
use crate::NotificationBuilder;
+1 -1
View File
@@ -2,7 +2,7 @@
// SPDX-License-Identifier: Apache-2.0
// SPDX-License-Identifier: MIT
use serde::{ser::Serializer, Serialize};
use serde::{Serialize, ser::Serializer};
/// Alias for a [`std::result::Result`] with the error type set to [`Error`].
pub type Result<T> = std::result::Result<T, Error>;
+3 -3
View File
@@ -14,13 +14,13 @@
)]
use serde::Serialize;
#[cfg(mobile)]
use tauri::plugin::PluginHandle;
#[cfg(desktop)]
use tauri::AppHandle;
#[cfg(mobile)]
use tauri::plugin::PluginHandle;
use tauri::{
plugin::{Builder, TauriPlugin},
Manager, Runtime,
plugin::{Builder, TauriPlugin},
};
pub use models::*;
+2 -2
View File
@@ -2,10 +2,10 @@
// SPDX-License-Identifier: Apache-2.0
// SPDX-License-Identifier: MIT
use serde::{de::DeserializeOwned, Deserialize};
use serde::{Deserialize, de::DeserializeOwned};
use tauri::{
plugin::{PermissionState, PluginApi, PluginHandle},
AppHandle, Runtime,
plugin::{PermissionState, PluginApi, PluginHandle},
};
use crate::models::*;
+4 -4
View File
@@ -4,7 +4,7 @@
use std::{collections::HashMap, fmt::Display};
use serde::{de::Error as DeError, Deserialize, Deserializer, Serialize, Serializer};
use serde::{Deserialize, Deserializer, Serialize, Serializer, de::Error as DeError};
use url::Url;
@@ -188,11 +188,11 @@ pub enum Schedule {
// custom ISO-8601 serialization that does not use 6 digits for years.
mod iso8601 {
use serde::{ser::Error as _, Serialize, Serializer};
use serde::{Serialize, Serializer, ser::Error as _};
use time::{
format_description::well_known::iso8601::{Config, EncodedConfig},
format_description::well_known::Iso8601,
OffsetDateTime,
format_description::well_known::Iso8601,
format_description::well_known::iso8601::{Config, EncodedConfig},
};
const SERDE_CONFIG: EncodedConfig = Config::DEFAULT.encode();
+2 -2
View File
@@ -5,11 +5,11 @@
use std::path::{Path, PathBuf};
use tauri::{
ipc::{CommandScope, GlobalScope},
AppHandle, Runtime,
ipc::{CommandScope, GlobalScope},
};
use crate::{scope::Scope, Error, OpenerExt};
use crate::{Error, OpenerExt, scope::Scope};
#[tauri::command]
pub async fn open_url<R: Runtime>(
+1 -1
View File
@@ -13,7 +13,7 @@
use std::path::Path;
use tauri::{plugin::TauriPlugin, Manager, Runtime};
use tauri::{Manager, Runtime, plugin::TauriPlugin};
#[cfg(mobile)]
use tauri::plugin::PluginHandle;
+3 -3
View File
@@ -93,18 +93,18 @@ mod imp {
use windows::Win32::UI::Shell::Common::ITEMIDLIST;
use windows::{
core::{w, HSTRING, PCWSTR},
Win32::{
Foundation::ERROR_FILE_NOT_FOUND,
System::Com::CoInitialize,
UI::{
Shell::{
ILCreateFromPathW, ILFree, SHOpenFolderAndSelectItems, ShellExecuteExW,
SHELLEXECUTEINFOW,
ILCreateFromPathW, ILFree, SHELLEXECUTEINFOW, SHOpenFolderAndSelectItems,
ShellExecuteExW,
},
WindowsAndMessaging::SW_SHOWNORMAL,
},
},
core::{HSTRING, PCWSTR, w},
};
pub fn reveal_items_in_dir(paths: &[PathBuf]) -> crate::Result<()> {
+2 -2
View File
@@ -8,9 +8,9 @@ use std::{
sync::Arc,
};
use tauri::{ipc::ScopeObject, utils::acl::Value, AppHandle, Manager, Runtime};
use tauri::{AppHandle, Manager, Runtime, ipc::ScopeObject, utils::acl::Value};
use crate::{scope_entry::EntryRaw, Error};
use crate::{Error, scope_entry::EntryRaw};
pub use crate::scope_entry::Application;
+1 -1
View File
@@ -10,7 +10,7 @@ use std::{
path::{Component, Path, PathBuf, Prefix, PrefixComponent},
};
use windows::{core::HSTRING, Win32::Storage::FileSystem::GetFullPathNameW};
use windows::{Win32::Storage::FileSystem::GetFullPathNameW, core::HSTRING};
pub fn absolute_and_check_exists(path: &Path) -> io::Result<PathBuf> {
let path = absolute(path)?;
+2 -2
View File
@@ -12,10 +12,10 @@
use std::fmt::Display;
pub use os_info::Version;
use serialize_to_javascript::{default_template, DefaultTemplate, Template};
use serialize_to_javascript::{DefaultTemplate, Template, default_template};
use tauri::{
plugin::{Builder, TauriPlugin},
Runtime,
plugin::{Builder, TauriPlugin},
};
mod commands;
+4 -5
View File
@@ -17,13 +17,13 @@ use aho_corasick::AhoCorasick;
use serde::{Deserialize, Serialize};
use tauri::{
plugin::{Builder, TauriPlugin},
Manager, Runtime,
plugin::{Builder, TauriPlugin},
};
use tauri_plugin_fs::FsExt;
use std::{
fs::{create_dir_all, File},
fs::{File, create_dir_all},
io::Write,
path::Path,
};
@@ -198,8 +198,8 @@ pub fn init<R: Runtime>() -> TauriPlugin<R> {
// We will still save some semi-broken values because the scope events are quite spammy and we don't want to reduce runtime performance any further.
let ac = AhoCorasick::new(PATTERNS).unwrap(/* This should be impossible to fail since we're using a small static input */);
if let Some(fs_scope) = &fs_scope {
if fs_scope_state_path.exists() {
if let Some(fs_scope) = &fs_scope
&& fs_scope_state_path.exists() {
let scope: Scope = std::fs::read(&fs_scope_state_path)
.map_err(Error::from)
.and_then(|scope| bincode::deserialize(&scope).map_err(Into::into))
@@ -218,7 +218,6 @@ pub fn init<R: Runtime>() -> TauriPlugin<R> {
// This is needed to fix broken .peristed-scope files in case the app doesn't update the scope itself.
save_scopes(fs_scope, &app_dir, &fs_scope_state_path);
}
}
#[cfg(feature = "protocol-asset")]
if asset_scope_state_path.exists() {
+2 -2
View File
@@ -21,12 +21,12 @@ mod ext;
pub use ext::*;
use tauri::{
plugin::{self, TauriPlugin},
Result, Runtime,
plugin::{self, TauriPlugin},
};
#[cfg(feature = "tray-icon")]
use tauri::{tray::TrayIconEvent, AppHandle, Manager, PhysicalPosition, PhysicalSize};
use tauri::{AppHandle, Manager, PhysicalPosition, PhysicalSize, tray::TrayIconEvent};
#[cfg(feature = "tray-icon")]
struct Tray(std::sync::Mutex<Option<(PhysicalPosition<f64>, PhysicalSize<f64>)>>);
+1 -1
View File
@@ -10,8 +10,8 @@
)]
use tauri::{
plugin::{Builder, TauriPlugin},
Runtime,
plugin::{Builder, TauriPlugin},
};
mod commands;
+2 -2
View File
@@ -7,16 +7,16 @@ use std::{collections::HashMap, future::Future, path::PathBuf, pin::Pin, string:
use encoding_rs::Encoding;
use serde::{Deserialize, Serialize};
use tauri::{
ipc::{Channel, CommandScope, GlobalScope},
Manager, Runtime, State, Window,
ipc::{Channel, CommandScope, GlobalScope},
};
#[allow(deprecated)]
use crate::open::Program;
use crate::{
Shell,
process::{CommandEvent, TerminatedPayload},
scope::ExecuteArgs,
Shell,
};
type ChildId = u32;
+1 -1
View File
@@ -19,8 +19,8 @@ use std::{
use process::{Command, CommandChild};
use regex::Regex;
use tauri::{
plugin::{Builder, TauriPlugin},
AppHandle, Manager, RunEvent, Runtime,
plugin::{Builder, TauriPlugin},
};
mod commands;
+2 -2
View File
@@ -20,10 +20,10 @@ use std::os::windows::process::CommandExt;
const CREATE_NO_WINDOW: u32 = 0x0800_0000;
const NEWLINE_BYTE: u8 = b'\n';
use tauri::async_runtime::{block_on as block_on_task, channel, Receiver, Sender};
use tauri::async_runtime::{Receiver, Sender, block_on as block_on_task, channel};
pub use encoding_rs::Encoding;
use os_pipe::{pipe, PipeReader, PipeWriter};
use os_pipe::{PipeReader, PipeWriter, pipe};
use serde::Serialize;
use shared_child::SharedChild;
use tauri::utils::platform;
+11 -7
View File
@@ -9,8 +9,8 @@ use crate::open::Program;
use crate::process::Command;
use regex::Regex;
use tauri::ipc::ScopeObject;
use tauri::Manager;
use tauri::ipc::ScopeObject;
/// Allowed representation of `Execute` command arguments.
#[derive(Debug, Clone, serde::Deserialize)]
@@ -162,8 +162,8 @@ pub enum Error {
/// The sidecar program validated but failed to find the sidecar path.
#[error(
"The scoped sidecar command was validated, but failed to create the path to the command: {0}"
)]
"The scoped sidecar command was validated, but failed to create the path to the command: {0}"
)]
Sidecar(String),
/// The named command was not found in the scoped config.
@@ -172,12 +172,14 @@ pub enum Error {
/// A command variable has no value set in the arguments.
#[error(
"Scoped command argument at position {0} must match regex validation {1} but it was not found"
)]
"Scoped command argument at position {0} must match regex validation {1} but it was not found"
)]
MissingVar(usize, String),
/// At least one argument did not pass input validation.
#[error("Scoped command argument at position {index} was found, but failed regex validation {validation}")]
#[error(
"Scoped command argument at position {index} was found, but failed regex validation {validation}"
)]
Validation {
/// Index of the variable.
index: usize,
@@ -214,7 +216,9 @@ impl OpenScope {
});
}
} else {
log::warn!("open() command called but the plugin configuration denies calls from JavaScript; set `tauri.conf.json > plugins > shell > open` to true or a validation regex string");
log::warn!(
"open() command called but the plugin configuration denies calls from JavaScript; set `tauri.conf.json > plugins > shell > open` to true or a validation regex string"
);
return Err(Error::Validation {
index: 0,
validation: "tauri^".to_string(), // purposefully impossible regex
+1 -1
View File
@@ -2,7 +2,7 @@
// SPDX-License-Identifier: Apache-2.0
// SPDX-License-Identifier: MIT
use serde::{de::Error as DeError, Deserialize, Deserializer};
use serde::{Deserialize, Deserializer, de::Error as DeError};
use std::path::PathBuf;
@@ -4,7 +4,7 @@ version = "0.1.0"
description = "A Tauri App"
authors = ["You"]
repository = ""
edition = "2021"
edition = "2024"
rust-version = "1.90"
[dependencies]
+1 -1
View File
@@ -15,7 +15,7 @@
)]
#![cfg(not(any(target_os = "android", target_os = "ios")))]
use tauri::{plugin::TauriPlugin, AppHandle, Manager, Runtime};
use tauri::{AppHandle, Manager, Runtime, plugin::TauriPlugin};
#[cfg(target_os = "windows")]
#[path = "platform_impl/windows.rs"]
@@ -7,8 +7,8 @@ use crate::semver_compat::semver_compat_string;
use crate::SingleInstanceCallback;
use tauri::{
plugin::{self, TauriPlugin},
AppHandle, Manager, RunEvent, Runtime,
plugin::{self, TauriPlugin},
};
use zbus::{blocking::Connection, interface, names::WellKnownName};
@@ -101,12 +101,11 @@ pub fn init<R: Runtime>(
}
pub fn destroy<R: Runtime, M: Manager<R>>(manager: &M) {
if let Some(connection) = manager.try_state::<ConnectionHandle>() {
if let Some(dbus_name) = manager
if let Some(connection) = manager.try_state::<ConnectionHandle>()
&& let Some(dbus_name) = manager
.try_state::<DBusName>()
.and_then(|name| WellKnownName::try_from(name.0.clone()).ok())
{
let _ = connection.0.release_name(dbus_name);
}
}
}
@@ -8,12 +8,12 @@ use std::{
path::PathBuf,
};
use crate::SingleInstanceCallback;
#[cfg(feature = "semver")]
use crate::semver_compat::semver_compat_string;
use crate::SingleInstanceCallback;
use tauri::{
plugin::{self, TauriPlugin},
AppHandle, Config, Manager, RunEvent, Runtime,
plugin::{self, TauriPlugin},
};
use tokio::io::AsyncReadExt;
@@ -8,20 +8,20 @@ use crate::semver_compat::semver_compat_string;
use crate::SingleInstanceCallback;
use std::ffi::CStr;
use tauri::{
plugin::{self, TauriPlugin},
AppHandle, Manager, RunEvent, Runtime,
plugin::{self, TauriPlugin},
};
use windows_sys::Win32::{
Foundation::{CloseHandle, GetLastError, ERROR_ALREADY_EXISTS, HWND, LPARAM, LRESULT, WPARAM},
Foundation::{CloseHandle, ERROR_ALREADY_EXISTS, GetLastError, HWND, LPARAM, LRESULT, WPARAM},
System::{
DataExchange::COPYDATASTRUCT,
LibraryLoader::GetModuleHandleW,
Threading::{CreateMutexW, ReleaseMutex},
},
UI::WindowsAndMessaging::{
self as w32wm, AllowSetForegroundWindow, CreateWindowExW, DefWindowProcW, DestroyWindow,
FindWindowW, GetWindowThreadProcessId, RegisterClassExW, SendMessageW, CREATESTRUCTW,
GWLP_USERDATA, GWL_STYLE, WINDOW_LONG_PTR_INDEX, WM_COPYDATA, WM_CREATE, WM_DESTROY,
self as w32wm, AllowSetForegroundWindow, CREATESTRUCTW, CreateWindowExW, DefWindowProcW,
DestroyWindow, FindWindowW, GWL_STYLE, GWLP_USERDATA, GetWindowThreadProcessId,
RegisterClassExW, SendMessageW, WINDOW_LONG_PTR_INDEX, WM_COPYDATA, WM_CREATE, WM_DESTROY,
WNDCLASSEXW, WS_EX_LAYERED, WS_EX_NOACTIVATE, WS_EX_TOOLWINDOW, WS_EX_TRANSPARENT,
WS_OVERLAPPED, WS_POPUP, WS_VISIBLE,
},
+1 -1
View File
@@ -5,7 +5,7 @@
use indexmap::IndexMap;
use serde_json::Value as JsonValue;
use sqlx::migrate::Migrator;
use tauri::{command, AppHandle, Runtime, State};
use tauri::{AppHandle, Runtime, State, command};
use crate::{DbInstances, DbPool, Error, LastInsertId, Migrations};
+1 -1
View File
@@ -3,7 +3,7 @@
// SPDX-License-Identifier: MIT
use serde_json::Value as JsonValue;
use sqlx::{mysql::MySqlValueRef, TypeInfo, Value, ValueRef};
use sqlx::{TypeInfo, Value, ValueRef, mysql::MySqlValueRef};
use time::{Date, OffsetDateTime, PrimitiveDateTime, Time};
use crate::Error;
+1 -1
View File
@@ -4,7 +4,7 @@
use rust_decimal::prelude::ToPrimitive;
use serde_json::Value as JsonValue;
use sqlx::{postgres::PgValueRef, TypeInfo, Value, ValueRef};
use sqlx::{TypeInfo, Value, ValueRef, postgres::PgValueRef};
use time::{Date, OffsetDateTime, PrimitiveDateTime, Time};
use uuid::Uuid;
+1 -1
View File
@@ -3,7 +3,7 @@
// SPDX-License-Identifier: MIT
use serde_json::Value as JsonValue;
use sqlx::{sqlite::SqliteValueRef, TypeInfo, Value, ValueRef};
use sqlx::{TypeInfo, Value, ValueRef, sqlite::SqliteValueRef};
use time::{Date, PrimitiveDateTime, Time};
use crate::Error;
+4 -2
View File
@@ -33,8 +33,8 @@ use sqlx::{
migrate::{Migration as SqlxMigration, MigrationSource, MigrationType, Migrator},
};
use tauri::{
plugin::{Builder as PluginBuilder, TauriPlugin},
Manager, RunEvent, Runtime,
plugin::{Builder as PluginBuilder, TauriPlugin},
};
use tokio::sync::{Mutex, RwLock};
@@ -158,7 +158,9 @@ impl Builder {
/// connected to in that case.
pub fn new() -> Self {
#[cfg(not(any(feature = "sqlite", feature = "mysql", feature = "postgres")))]
eprintln!("No sql driver enabled. Please set at least one of the \"sqlite\", \"mysql\", \"postgres\" feature flags.");
eprintln!(
"No sql driver enabled. Please set at least one of the \"sqlite\", \"mysql\", \"postgres\" feature flags."
);
Self::default()
}
+1 -1
View File
@@ -8,7 +8,7 @@ use std::fs::create_dir_all;
use indexmap::IndexMap;
use serde_json::Value as JsonValue;
#[cfg(any(feature = "sqlite", feature = "mysql", feature = "postgres"))]
use sqlx::{migrate::MigrateDatabase, Column, Executor, Pool, Row};
use sqlx::{Column, Executor, Pool, Row, migrate::MigrateDatabase};
#[cfg(any(feature = "sqlite", feature = "mysql", feature = "postgres"))]
use tauri::Manager;
use tauri::{AppHandle, Runtime};
@@ -5,7 +5,7 @@ description = "A Tauri App"
authors = ["you"]
license = ""
repository = ""
edition = "2021"
edition = "2024"
# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html
+4 -5
View File
@@ -18,10 +18,10 @@ use std::{
sync::{Arc, RwLock},
time::Duration,
};
pub use store::{resolve_store_path, DeserializeFn, SerializeFn, Store, StoreBuilder};
pub use store::{DeserializeFn, SerializeFn, Store, StoreBuilder, resolve_store_path};
use tauri::{
plugin::{self, TauriPlugin},
AppHandle, Manager, ResourceId, RunEvent, Runtime, State,
plugin::{self, TauriPlugin},
};
mod error;
@@ -470,11 +470,10 @@ impl Builder {
let collection = app_handle.state::<StoreState>();
let stores = collection.stores.read().unwrap();
for (path, rid) in stores.iter() {
if let Ok(store) = app_handle.resources_table().get::<Store<R>>(*rid) {
if let Err(err) = store.save() {
if let Ok(store) = app_handle.resources_table().get::<Store<R>>(*rid)
&& let Err(err) = store.save() {
tracing::error!("failed to save store {path:?} with error {err:?}");
}
}
}
}
})
+2 -2
View File
@@ -11,10 +11,10 @@ use std::{
sync::{Arc, Mutex},
time::Duration,
};
use tauri::{path::BaseDirectory, AppHandle, Emitter, Manager, Resource, ResourceId, Runtime};
use tauri::{AppHandle, Emitter, Manager, Resource, ResourceId, Runtime, path::BaseDirectory};
use tokio::{
select,
sync::mpsc::{unbounded_channel, UnboundedSender},
sync::mpsc::{UnboundedSender, unbounded_channel},
time::sleep,
};
+2 -2
View File
@@ -45,8 +45,8 @@ fn create_or_get_salt(salt: &mut [u8], salt_path: &Path) {
salt.clone_from_slice(&tmp);
} else {
// Generate new salt
let mut gen = ChaCha20Rng::from_os_rng();
gen.fill_bytes(salt);
let mut rng = ChaCha20Rng::from_os_rng();
rng.fill_bytes(salt);
std::fs::write(salt_path, salt).expect("Failed to write salt for Stronghold")
}
}
+5 -6
View File
@@ -23,18 +23,18 @@ use std::{
use crypto::keys::bip39;
use iota_stronghold::{
Client, Location,
procedures::{
BIP39Generate, BIP39Recover, Curve, Ed25519Sign, KeyType as StrongholdKeyType,
MnemonicLanguage, PublicKey, Slip10Derive, Slip10DeriveInput, Slip10Generate,
StrongholdProcedure,
},
Client, Location,
};
use serde::{de::Visitor, Deserialize, Deserializer};
use serde::{Deserialize, Deserializer, de::Visitor};
use stronghold::{Error, Result, Stronghold};
use tauri::{
plugin::{Builder as PluginBuilder, TauriPlugin},
Manager, Runtime, State,
plugin::{Builder as PluginBuilder, TauriPlugin},
};
use zeroize::{Zeroize, Zeroizing};
@@ -270,12 +270,11 @@ async fn destroy(
snapshot_path: PathBuf,
) -> Result<()> {
let mut collection = collection.0.lock().unwrap();
if let Some(stronghold) = collection.remove(&snapshot_path) {
if let Err(e) = stronghold.save() {
if let Some(stronghold) = collection.remove(&snapshot_path)
&& let Err(e) = stronghold.save() {
collection.insert(snapshot_path, stronghold);
return Err(e);
}
}
Ok(())
}
+1 -1
View File
@@ -6,7 +6,7 @@ use crate::{Result, Update, UpdaterExt};
use http::{HeaderMap, HeaderName, HeaderValue};
use serde::Serialize;
use tauri::{ipc::Channel, Manager, Resource, ResourceId, Runtime, Webview};
use tauri::{Manager, Resource, ResourceId, Runtime, Webview, ipc::Channel};
use std::{str::FromStr, time::Duration};
use url::Url;
+6 -2
View File
@@ -204,8 +204,12 @@ pub(crate) fn validate_endpoints(
if url.scheme() != "https" {
#[cfg(debug_assertions)]
{
eprintln!("[\x1b[33mWARNING\x1b[0m] The updater endpoint \"{url}\" doesn't use `https` protocol. This is allowed in development but will fail in release builds.");
eprintln!("[\x1b[33mWARNING\x1b[0m] if this is a desired behavior, you can enable `dangerousInsecureTransportProtocol` in the plugin configuration");
eprintln!(
"[\x1b[33mWARNING\x1b[0m] The updater endpoint \"{url}\" doesn't use `https` protocol. This is allowed in development but will fail in release builds."
);
eprintln!(
"[\x1b[33mWARNING\x1b[0m] if this is a desired behavior, you can enable `dangerousInsecureTransportProtocol` in the plugin configuration"
);
}
#[cfg(not(debug_assertions))]
return Err(crate::Error::InsecureTransportProtocol);
+7 -5
View File
@@ -25,7 +25,9 @@ pub enum Error {
#[error("Could not fetch a valid release JSON from the remote")]
ReleaseNotFound,
/// Unsupported app architecture.
#[error("Unsupported application architecture, expected one of `x86`, `x86_64`, `arm` or `aarch64`.")]
#[error(
"Unsupported application architecture, expected one of `x86`, `x86_64`, `arm` or `aarch64`."
)]
UnsupportedArch,
/// Operating system is not supported.
#[error("Unsupported OS, expected one of `linux`, `darwin` or `windows`.")]
@@ -43,9 +45,7 @@ pub enum Error {
#[error("the platform `{0}` was not found in the response `platforms` object")]
TargetNotFound(String),
/// Neither the platform nor the fallback platform was found in the updater JSON response.
#[error(
"None of the fallback platforms `{0:?}` were found in the response `platforms` object"
)]
#[error("None of the fallback platforms `{0:?}` were found in the response `platforms` object")]
TargetsNotFound(Vec<String>),
/// Download failed
#[error("`{0}`")]
@@ -57,7 +57,9 @@ pub enum Error {
#[error(transparent)]
Base64(#[from] base64::DecodeError),
/// UTF8 Errors in signature.
#[error("The signature {0} could not be decoded, please check if it is a valid base64 string. The signature must be the contents of the `.sig` file generated by the Tauri bundler, as a string.")]
#[error(
"The signature {0} could not be decoded, please check if it is a valid base64 string. The signature must be the contents of the `.sig` file generated by the Tauri bundler, as a string."
)]
SignatureUtf8(String),
#[cfg(all(target_os = "windows", feature = "zip"))]
/// `zip` errors.
+1 -1
View File
@@ -24,8 +24,8 @@ use std::{ffi::OsString, sync::Arc};
use http::{HeaderMap, HeaderName, HeaderValue};
use semver::Version;
use tauri::{
plugin::{Builder as PluginBuilder, TauriPlugin},
Manager, Runtime,
plugin::{Builder as PluginBuilder, TauriPlugin},
};
mod commands;
+15 -21
View File
@@ -17,28 +17,28 @@ use std::ffi::OsStr;
use base64::Engine;
use futures_util::StreamExt;
use http::{header::ACCEPT, HeaderName};
use http::{HeaderName, header::ACCEPT};
use minisign_verify::{PublicKey, Signature};
use percent_encoding::{AsciiSet, CONTROLS};
use reqwest::{
header::{HeaderMap, HeaderValue},
ClientBuilder, StatusCode,
header::{HeaderMap, HeaderValue},
};
use semver::Version;
use serde::{de::Error as DeError, Deserialize, Deserializer, Serialize};
use serde::{Deserialize, Deserializer, Serialize, de::Error as DeError};
use tauri::{
AppHandle, Resource, Runtime,
utils::{
config::BundleType,
platform::{bundle_type, current_exe},
},
AppHandle, Resource, Runtime,
};
use time::OffsetDateTime;
use url::Url;
use crate::{
error::{Error, Result},
Config,
error::{Error, Result},
};
const UPDATER_USER_AGENT: &str = concat!(env!("CARGO_PKG_NAME"), "/", env!("CARGO_PKG_VERSION"),);
@@ -937,8 +937,8 @@ impl Update {
/// └── ...
fn install_inner(&self, bytes: &[u8]) -> Result<()> {
use windows_sys::{
w,
Win32::UI::{Shell::ShellExecuteW, WindowsAndMessaging::SW_SHOW},
w,
};
let updater_type = self.extract(bytes)?;
@@ -1185,8 +1185,8 @@ impl Update {
let decoder = flate2::read::GzDecoder::new(archive);
let mut archive = tar::Archive::new(decoder);
for mut entry in archive.entries()?.flatten() {
if let Ok(path) = entry.path() {
if path.extension() == Some(OsStr::new("AppImage")) {
if let Ok(path) = entry.path()
&& path.extension() == Some(OsStr::new("AppImage")) {
// if something went wrong during the extraction, we should restore previous app
if let Err(err) = entry.unpack(&self.extract_path) {
std::fs::rename(tmp_app_image, &self.extract_path)?;
@@ -1195,7 +1195,6 @@ impl Update {
// early finish we have everything we need here
return Ok(());
}
}
}
// if we have not returned early we should restore the backup
std::fs::rename(tmp_app_image, &self.extract_path)?;
@@ -1289,20 +1288,17 @@ impl Update {
.arg(install_arg)
.arg(pkg_path)
.status()
{
if status.success() {
&& status.success() {
log::debug!("installed {pkg_path:?} with pkexec");
return Ok(());
}
}
// 2. Try zenity or kdialog for a graphical sudo experience
if let Ok(password) = self.get_password_graphically() {
if self.install_with_sudo(pkg_path, &password, install_cmd, install_arg)? {
if let Ok(password) = self.get_password_graphically()
&& self.install_with_sudo(pkg_path, &password, install_cmd, install_arg)? {
log::debug!("installed {pkg_path:?} with GUI sudo");
return Ok(());
}
}
// 3. Final fallback: terminal sudo
let status = std::process::Command::new("sudo")
@@ -1329,22 +1325,20 @@ impl Update {
])
.output();
if let Ok(output) = zenity_result {
if output.status.success() {
if let Ok(output) = zenity_result
&& output.status.success() {
return Ok(String::from_utf8_lossy(&output.stdout).trim().to_string());
}
}
// Fall back to kdialog if zenity fails or isn't available
let kdialog_result = std::process::Command::new("kdialog")
.args(["--password", "Enter your password to install the update:"])
.output();
if let Ok(output) = kdialog_result {
if output.status.success() {
if let Ok(output) = kdialog_result
&& output.status.success() {
return Ok(String::from_utf8_lossy(&output.stdout).trim().to_string());
}
}
Err(Error::AuthenticationFailed)
}
@@ -818,7 +818,8 @@ fn run_update_cases(
if code != expected_exit_code {
panic!(
"failed to run app bundled as {}, expected exit code {expected_exit_code}, got {code}", bundle_target.name()
"failed to run app bundled as {}, expected exit code {expected_exit_code}, got {code}",
bundle_target.name()
);
}
#[cfg(windows)]
@@ -32,7 +32,7 @@ fn npm_command() -> Command {
}
mod v1 {
use super::{npm_command, BundleTarget, UPDATER_PRIVATE_KEY};
use super::{BundleTarget, UPDATER_PRIVATE_KEY, npm_command};
use serde::Serialize;
use std::{
path::{Path, PathBuf},
@@ -3,7 +3,7 @@ workspace = {}
[package]
name = "app-updater-v1"
version = "0.1.0"
edition = "2021"
edition = "2024"
[build-dependencies]
tauri-build = { version = "1", features = [] }
+2 -3
View File
@@ -21,12 +21,11 @@ mod transfer_stats;
use transfer_stats::TransferStats;
use futures_util::TryStreamExt;
use serde::{ser::Serializer, Deserialize, Serialize};
use serde::{Deserialize, Serialize, ser::Serializer};
use tauri::{
command,
Runtime, command,
ipc::Channel,
plugin::{Builder as PluginBuilder, TauriPlugin},
Runtime,
};
use tokio::{
fs::File,
@@ -2,7 +2,7 @@
name = "websocket-example"
version = "0.1.0"
description = "A Tauri App"
edition = "2021"
edition = "2024"
[dependencies]
serde = { workspace = true }
+5 -5
View File
@@ -18,13 +18,13 @@
html_favicon_url = "https://github.com/tauri-apps/tauri/raw/dev/app-icon.png"
)]
use futures_util::{stream::SplitSink, SinkExt, StreamExt};
use futures_util::{SinkExt, StreamExt, stream::SplitSink};
use http::header::{HeaderName, HeaderValue};
use serde::{ser::Serializer, Deserialize, Serialize};
use serde::{Deserialize, Serialize, ser::Serializer};
use tauri::{
Manager, Runtime, State, Window,
ipc::Channel,
plugin::{Builder as PluginBuilder, TauriPlugin},
Manager, Runtime, State, Window,
};
use tokio::{net::TcpStream, sync::Mutex};
#[cfg(any(
@@ -40,12 +40,12 @@ use tokio_tungstenite::connect_async_tls_with_config;
)))]
use tokio_tungstenite::connect_async_with_config;
use tokio_tungstenite::{
Connector, MaybeTlsStream, WebSocketStream,
tungstenite::{
Message,
client::IntoClientRequest,
protocol::{CloseFrame as ProtocolCloseFrame, WebSocketConfig},
Message,
},
Connector, MaybeTlsStream, WebSocketStream,
};
use std::collections::HashMap;
+1 -1
View File
@@ -3,7 +3,7 @@
// SPDX-License-Identifier: MIT
use crate::{AppHandleExt, StateFlags, WindowExt};
use tauri::{command, AppHandle, Manager, Runtime};
use tauri::{AppHandle, Manager, Runtime, command};
fn get_state_flags<R: Runtime>(
app: &AppHandle<R>,
+1 -1
View File
@@ -13,9 +13,9 @@
use bitflags::bitflags;
use serde::{Deserialize, Serialize};
use tauri::{
plugin::{Builder as PluginBuilder, TauriPlugin},
AppHandle, Manager, Monitor, PhysicalPosition, PhysicalSize, RunEvent, Runtime, WebviewWindow,
Window, WindowEvent,
plugin::{Builder as PluginBuilder, TauriPlugin},
};
use std::{