2022-08-28 21:13:21 +03:00
// Copyright 2019-2022 Tauri Programme within The Commons Conservancy
2021-04-11 01:09:09 +03:00
// SPDX-License-Identifier: Apache-2.0
// SPDX-License-Identifier: MIT
2020-06-28 16:34:43 +03:00
//! Tauri utility helpers
#![ warn(missing_docs, rust_2018_idioms) ]
2022-04-21 21:03:29 +03:00
use std ::fmt ::Display ;
2022-05-25 19:15:21 +03:00
use semver ::Version ;
2022-04-21 21:03:29 +03:00
use serde ::{ Deserialize , Deserializer , Serialize , Serializer } ;
2021-02-09 21:22:04 +03:00
pub mod assets ;
pub mod config ;
2021-05-05 05:31:05 +03:00
pub mod html ;
2022-04-22 18:59:03 +03:00
pub mod io ;
2022-09-28 19:16:58 +03:00
pub mod mime_type ;
2020-01-18 03:33:17 +03:00
pub mod platform ;
2022-02-08 19:13:21 +03:00
/// Prepare application resources and sidecars.
#[ cfg(feature = " resources " ) ]
pub mod resources ;
2020-01-18 03:33:17 +03:00
2022-01-17 16:46:14 +03:00
/// Application pattern.
pub mod pattern ;
2021-08-15 18:06:46 +03:00
/// `tauri::App` package information.
2021-05-10 06:01:12 +03:00
#[ derive(Debug, Clone) ]
pub struct PackageInfo {
2021-08-15 18:06:46 +03:00
/// App name
2021-05-10 06:01:12 +03:00
pub name : String ,
2021-08-15 18:06:46 +03:00
/// App version
2022-05-25 19:15:21 +03:00
pub version : Version ,
2021-12-09 05:47:43 +03:00
/// The crate authors.
pub authors : & 'static str ,
/// The crate description.
pub description : & 'static str ,
2021-05-10 06:01:12 +03:00
}
impl PackageInfo {
/// Returns the application package name.
/// On macOS and Windows it's the `name` field, and on Linux it's the `name` in `kebab-case`.
pub fn package_name ( & self ) -> String {
2021-08-23 02:41:26 +03:00
#[ cfg(target_os = " linux " ) ]
{
2021-12-15 22:02:48 +03:00
use heck ::ToKebabCase ;
2021-08-23 02:41:26 +03:00
self . name . clone ( ) . to_kebab_case ( )
}
#[ cfg(not(target_os = " linux " )) ]
2021-08-10 22:02:46 +03:00
self . name . clone ( )
2021-05-10 06:01:12 +03:00
}
}
2022-11-18 00:47:54 +03:00
/// How the window title bar should be displayed on macOS.
2022-09-30 23:15:45 +03:00
#[ derive(Debug, Clone, PartialEq, Eq) ]
#[ cfg_attr(feature = " schema " , derive(schemars::JsonSchema)) ]
pub enum TitleBarStyle {
/// A normal title bar.
Visible ,
/// Makes the title bar transparent, so the window background color is shown instead.
///
/// Useful if you don't need to have actual HTML under the title bar. This lets you avoid the caveats of using `TitleBarStyle::Overlay`. Will be more useful when Tauri lets you set a custom window background color.
Transparent ,
/// Shows the title bar as a transparent overlay over the window's content.
///
/// Keep in mind:
/// - The height of the title bar is different on different OS versions, which can lead to window the controls and title not being where you don't expect.
2022-11-18 00:47:54 +03:00
/// - You need to define a custom drag region to make your window draggable, however due to a limitation you can't drag the window when it's not in focus <https://github.com/tauri-apps/tauri/issues/4316>.
2022-09-30 23:15:45 +03:00
/// - The color of the window title depends on the system theme.
Overlay ,
}
impl Default for TitleBarStyle {
fn default ( ) -> Self {
Self ::Visible
}
}
impl Serialize for TitleBarStyle {
fn serialize < S > ( & self , serializer : S ) -> std ::result ::Result < S ::Ok , S ::Error >
where
S : Serializer ,
{
serializer . serialize_str ( self . to_string ( ) . as_ref ( ) )
}
}
impl < ' de > Deserialize < ' de > for TitleBarStyle {
fn deserialize < D > ( deserializer : D ) -> std ::result ::Result < Self , D ::Error >
where
D : Deserializer < ' de > ,
{
let s = String ::deserialize ( deserializer ) ? ;
Ok ( match s . to_lowercase ( ) . as_str ( ) {
" transparent " = > Self ::Transparent ,
" overlay " = > Self ::Overlay ,
_ = > Self ::Visible ,
} )
}
}
impl Display for TitleBarStyle {
fn fmt ( & self , f : & mut std ::fmt ::Formatter < '_ > ) -> std ::fmt ::Result {
write! (
f ,
" {} " ,
match self {
Self ::Visible = > " Visible " ,
Self ::Transparent = > " Transparent " ,
Self ::Overlay = > " Overlay " ,
}
)
}
}
2022-04-21 21:03:29 +03:00
/// System theme.
#[ derive(Debug, Copy, Clone, PartialEq, Eq) ]
#[ cfg_attr(feature = " schema " , derive(schemars::JsonSchema)) ]
#[ non_exhaustive ]
pub enum Theme {
/// Light theme.
Light ,
/// Dark theme.
Dark ,
}
impl Serialize for Theme {
fn serialize < S > ( & self , serializer : S ) -> std ::result ::Result < S ::Ok , S ::Error >
where
S : Serializer ,
{
serializer . serialize_str ( self . to_string ( ) . as_ref ( ) )
}
}
impl < ' de > Deserialize < ' de > for Theme {
fn deserialize < D > ( deserializer : D ) -> std ::result ::Result < Self , D ::Error >
where
D : Deserializer < ' de > ,
{
let s = String ::deserialize ( deserializer ) ? ;
Ok ( match s . to_lowercase ( ) . as_str ( ) {
" dark " = > Self ::Dark ,
_ = > Self ::Light ,
} )
}
}
impl Display for Theme {
fn fmt ( & self , f : & mut std ::fmt ::Formatter < '_ > ) -> std ::fmt ::Result {
write! (
f ,
" {} " ,
match self {
Self ::Light = > " light " ,
Self ::Dark = > " dark " ,
}
)
}
}
2022-01-09 16:57:29 +03:00
/// Information about environment variables.
#[ derive(Debug, Clone) ]
2021-10-24 15:24:18 +03:00
#[ non_exhaustive ]
2022-01-09 16:57:29 +03:00
pub struct Env {
/// The APPIMAGE environment variable.
#[ cfg(target_os = " linux " ) ]
pub appimage : Option < std ::ffi ::OsString > ,
/// The APPDIR environment variable.
#[ cfg(target_os = " linux " ) ]
pub appdir : Option < std ::ffi ::OsString > ,
2022-07-25 16:59:24 +03:00
/// The command line arguments of the current process.
pub args : Vec < String > ,
2022-01-09 16:57:29 +03:00
}
2022-01-09 20:26:58 +03:00
#[ allow(clippy::derivable_impls) ]
2022-01-09 16:57:29 +03:00
impl Default for Env {
fn default ( ) -> Self {
2022-07-25 16:59:24 +03:00
let args = std ::env ::args ( ) . skip ( 1 ) . collect ( ) ;
2021-10-25 20:01:16 +03:00
#[ cfg(target_os = " linux " ) ]
2022-01-09 21:35:23 +03:00
{
let env = Self {
#[ cfg(target_os = " linux " ) ]
appimage : std ::env ::var_os ( " APPIMAGE " ) ,
#[ cfg(target_os = " linux " ) ]
appdir : std ::env ::var_os ( " APPDIR " ) ,
2022-07-25 16:59:24 +03:00
args ,
2022-01-09 21:35:23 +03:00
} ;
if env . appimage . is_some ( ) | | env . appdir . is_some ( ) {
// validate that we're actually running on an AppImage
2022-01-29 02:13:41 +03:00
// an AppImage is mounted to `/$TEMPDIR/.mount_${appPrefix}${hash}`
2022-01-09 21:35:23 +03:00
// see https://github.com/AppImage/AppImageKit/blob/1681fd84dbe09c7d9b22e13cdb16ea601aa0ec47/src/runtime.c#L501
2021-11-17 20:38:10 +03:00
// note that it is safe to use `std::env::current_exe` here since we just loaded an AppImage.
2022-02-02 05:30:52 +03:00
let is_temp = std ::env ::current_exe ( )
2022-01-29 02:13:41 +03:00
. map ( | p | {
p . display ( )
. to_string ( )
. starts_with ( & format! ( " {} /.mount_ " , std ::env ::temp_dir ( ) . display ( ) ) )
} )
2022-02-02 05:30:52 +03:00
. unwrap_or ( true ) ;
if ! is_temp {
2022-01-09 21:35:23 +03:00
panic! ( " `APPDIR` or `APPIMAGE` environment variable found but this application was not detected as an AppImage; this might be a security issue. " ) ;
}
2021-10-24 15:24:18 +03:00
}
2022-01-09 21:35:23 +03:00
env
}
#[ cfg(not(target_os = " linux " )) ]
{
2022-07-25 16:59:24 +03:00
Self { args }
2022-01-09 16:57:29 +03:00
}
}
}
2021-08-15 18:06:46 +03:00
/// The result type of `tauri-utils`.
2021-02-11 01:51:15 +03:00
pub type Result < T > = std ::result ::Result < T , Error > ;
2020-01-18 03:33:17 +03:00
2021-08-15 18:06:46 +03:00
/// The error type of `tauri-utils`.
2021-02-11 01:51:15 +03:00
#[ derive(Debug, thiserror::Error) ]
2021-05-06 04:22:45 +03:00
#[ non_exhaustive ]
2020-05-30 02:22:04 +03:00
pub enum Error {
2020-06-28 16:34:43 +03:00
/// Target triple architecture error
2020-06-18 00:11:11 +03:00
#[ error( " Unable to determine target-architecture " ) ]
Architecture ,
2020-06-28 16:34:43 +03:00
/// Target triple OS error
2020-06-18 00:11:11 +03:00
#[ error( " Unable to determine target-os " ) ]
2021-04-12 16:44:44 +03:00
Os ,
2020-06-28 16:34:43 +03:00
/// Target triple environment error
2020-06-18 00:11:11 +03:00
#[ error( " Unable to determine target-environment " ) ]
Environment ,
2021-08-15 18:06:46 +03:00
/// Tried to get resource on an unsupported platform
2021-02-11 01:51:15 +03:00
#[ error( " Unsupported platform for reading resources " ) ]
UnsupportedPlatform ,
2020-06-28 16:34:43 +03:00
/// Get parent process error
2020-06-18 00:11:11 +03:00
#[ error( " Could not get parent process " ) ]
ParentProcess ,
2020-06-28 16:34:43 +03:00
/// Get parent process PID error
2020-06-18 00:11:11 +03:00
#[ error( " Could not get parent PID " ) ]
2021-04-12 16:44:44 +03:00
ParentPid ,
2020-06-28 16:34:43 +03:00
/// Get child process error
2020-06-18 00:11:11 +03:00
#[ error( " Could not get child process " ) ]
ChildProcess ,
2021-08-15 18:06:46 +03:00
/// IO error
2021-02-11 01:51:15 +03:00
#[ error( " {0} " ) ]
Io ( #[ from ] std ::io ::Error ) ,
2022-01-17 16:46:14 +03:00
/// Invalid pattern.
#[ error( " invalid pattern `{0}`. Expected either `brownfield` or `isolation`. " ) ]
InvalidPattern ( String ) ,
2022-02-08 19:13:21 +03:00
/// Invalid glob pattern.
#[ cfg(feature = " resources " ) ]
#[ error( " {0} " ) ]
GlobPattern ( #[ from ] glob ::PatternError ) ,
/// Failed to use glob pattern.
#[ cfg(feature = " resources " ) ]
#[ error( " `{0}` " ) ]
Glob ( #[ from ] glob ::GlobError ) ,
/// Glob pattern did not find any results.
#[ cfg(feature = " resources " ) ]
#[ error( " path matching {0} not found. " ) ]
GlobPathNotFound ( String ) ,
/// Error walking directory.
#[ cfg(feature = " resources " ) ]
#[ error( " {0} " ) ]
WalkdirError ( #[ from ] walkdir ::Error ) ,
/// Not allowed to walk dir.
#[ cfg(feature = " resources " ) ]
#[ error( " could not walk directory `{0}`, try changing `allow_walk` to true on the `ResourcePaths` constructor. " ) ]
NotAllowedToWalkDir ( std ::path ::PathBuf ) ,
2020-06-18 00:11:11 +03:00
}
2022-06-21 19:19:57 +03:00
/// Suppresses the unused-variable warnings of the given inputs.
///
/// This does not move any values. Instead, it just suppresses the warning by taking a
/// reference to the value.
#[ macro_export ]
macro_rules ! consume_unused_variable {
( $( $arg :expr ) , * ) = > {
$(
let _ = & $arg ;
) *
( )
} ;
}
/// Prints to the standard error, with a newline.
///
/// Equivalent to the [`eprintln!`] macro, except that it's only effective for debug builds.
#[ macro_export ]
macro_rules ! debug_eprintln {
( ) = > ( $crate ::debug_eprintln! ( " " ) ) ;
( $( $arg :tt ) * ) = > {
#[ cfg(debug_assertions) ]
eprintln! ( $( $arg ) * ) ;
#[ cfg(not(debug_assertions)) ]
$crate ::consume_unused_variable! ( $( $arg ) * ) ;
} ;
}