mirror of
https://github.com/tauri-apps/tauri.git
synced 2026-04-01 10:01:07 +02:00
feat(tauri) make Config globally available (#681)
This commit is contained in:
committed by
GitHub
parent
ea74c5cc01
commit
d3c53ebf30
@@ -33,6 +33,7 @@ tauri-utils = {version = "0.5", path = "../tauri-utils"}
|
||||
envmnt = "0.8.2"
|
||||
clap = { git = "https://github.com/clap-rs/clap", rev = "1a276f8", version = "3.0.0-beta.1", optional = true }
|
||||
notify-rust = { version = "4.0.0", optional = true }
|
||||
once_cell = "1.4.0"
|
||||
|
||||
[dev-dependencies]
|
||||
quickcheck = "0.9.2"
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
use crate::config::{Cli, Config};
|
||||
use crate::config::{get as get_config, Cli};
|
||||
|
||||
use clap::{App, Arg, ArgMatches};
|
||||
use serde::Serialize;
|
||||
@@ -36,16 +36,21 @@ impl Matches {
|
||||
}
|
||||
}
|
||||
|
||||
pub fn get_matches(config: Config) -> Matches {
|
||||
let cli = config.tauri.cli.unwrap();
|
||||
pub fn get_matches() -> crate::Result<Matches> {
|
||||
let config = get_config()?;
|
||||
let cli = config
|
||||
.tauri
|
||||
.cli
|
||||
.as_ref()
|
||||
.ok_or(anyhow::anyhow!("CLI configuration not defined"))?;
|
||||
|
||||
let about = cli
|
||||
.description()
|
||||
.unwrap_or(&crate_description!().to_string())
|
||||
.to_string();
|
||||
let app = get_app(crate_name!(), Some(&about), &cli);
|
||||
let app = get_app(crate_name!(), Some(&about), cli);
|
||||
let matches = app.get_matches();
|
||||
get_matches_internal(&cli, &matches)
|
||||
Ok(get_matches_internal(cli, &matches))
|
||||
}
|
||||
|
||||
fn get_matches_internal<T: Cli + 'static>(config: &T, matches: &ArgMatches) -> Matches {
|
||||
|
||||
@@ -1,9 +1,12 @@
|
||||
use serde::Deserialize;
|
||||
|
||||
use once_cell::sync::OnceCell;
|
||||
use std::collections::HashMap;
|
||||
use std::{fs, path};
|
||||
|
||||
#[derive(PartialEq, Deserialize, Clone, Debug)]
|
||||
static CONFIG: OnceCell<Config> = OnceCell::new();
|
||||
|
||||
#[derive(PartialEq, Deserialize, Debug)]
|
||||
#[serde(tag = "window", rename_all = "camelCase")]
|
||||
pub struct WindowConfig {
|
||||
#[serde(default = "default_width")]
|
||||
@@ -44,7 +47,7 @@ fn default_window() -> WindowConfig {
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(PartialEq, Deserialize, Clone, Debug)]
|
||||
#[derive(PartialEq, Deserialize, Debug)]
|
||||
#[serde(tag = "embeddedServer", rename_all = "camelCase")]
|
||||
pub struct EmbeddedServerConfig {
|
||||
#[serde(default = "default_host")]
|
||||
@@ -68,7 +71,7 @@ fn default_embedded_server() -> EmbeddedServerConfig {
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(PartialEq, Deserialize, Clone, Debug, Default)]
|
||||
#[derive(PartialEq, Deserialize, Debug, Default)]
|
||||
#[serde(rename_all = "camelCase")]
|
||||
pub struct CliArg {
|
||||
pub short: Option<char>,
|
||||
@@ -95,7 +98,7 @@ pub struct CliArg {
|
||||
pub require_equals: Option<bool>,
|
||||
}
|
||||
|
||||
#[derive(PartialEq, Deserialize, Clone, Debug)]
|
||||
#[derive(PartialEq, Deserialize, Debug)]
|
||||
#[serde(rename_all = "camelCase")]
|
||||
pub struct CliSubcommand {
|
||||
description: Option<String>,
|
||||
@@ -106,7 +109,7 @@ pub struct CliSubcommand {
|
||||
subcommands: Option<HashMap<String, CliSubcommand>>,
|
||||
}
|
||||
|
||||
#[derive(PartialEq, Deserialize, Clone, Debug)]
|
||||
#[derive(PartialEq, Deserialize, Debug)]
|
||||
#[serde(tag = "cli", rename_all = "camelCase")]
|
||||
pub struct CliConfig {
|
||||
description: Option<String>,
|
||||
@@ -159,7 +162,7 @@ macro_rules! impl_cli {
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(PartialEq, Deserialize, Clone, Debug)]
|
||||
#[derive(PartialEq, Deserialize, Debug)]
|
||||
#[serde(tag = "bundle", rename_all = "camelCase")]
|
||||
pub struct BundleConfig {
|
||||
pub identifier: String,
|
||||
@@ -173,7 +176,7 @@ fn default_bundle() -> BundleConfig {
|
||||
|
||||
impl_cli!(CliSubcommand, CliConfig);
|
||||
|
||||
#[derive(PartialEq, Deserialize, Clone, Debug)]
|
||||
#[derive(PartialEq, Deserialize, Debug)]
|
||||
#[serde(tag = "tauri", rename_all = "camelCase")]
|
||||
pub struct TauriConfig {
|
||||
#[serde(default = "default_window")]
|
||||
@@ -186,7 +189,7 @@ pub struct TauriConfig {
|
||||
pub bundle: BundleConfig,
|
||||
}
|
||||
|
||||
#[derive(PartialEq, Deserialize, Clone, Debug)]
|
||||
#[derive(PartialEq, Deserialize, Debug)]
|
||||
#[serde(tag = "build", rename_all = "camelCase")]
|
||||
pub struct BuildConfig {
|
||||
#[serde(default = "default_dev_path")]
|
||||
@@ -197,7 +200,7 @@ fn default_dev_path() -> String {
|
||||
"".to_string()
|
||||
}
|
||||
|
||||
#[derive(PartialEq, Deserialize, Clone, Debug)]
|
||||
#[derive(PartialEq, Deserialize, Debug)]
|
||||
#[serde(rename_all = "camelCase")]
|
||||
pub struct Config {
|
||||
#[serde(default = "default_tauri")]
|
||||
@@ -221,17 +224,27 @@ fn default_build() -> BuildConfig {
|
||||
}
|
||||
}
|
||||
|
||||
pub fn get() -> crate::Result<Config> {
|
||||
match option_env!("TAURI_CONFIG") {
|
||||
Some(config) => Ok(serde_json::from_str(config).expect("failed to parse TAURI_CONFIG env")),
|
||||
pub fn get() -> crate::Result<&'static Config> {
|
||||
if let Some(config) = CONFIG.get() {
|
||||
return Ok(config);
|
||||
}
|
||||
let config: Config = match option_env!("TAURI_CONFIG") {
|
||||
Some(config) => serde_json::from_str(config).expect("failed to parse TAURI_CONFIG env"),
|
||||
None => {
|
||||
let env_var = envmnt::get_or("TAURI_DIR", "../dist");
|
||||
let path = path::Path::new(&env_var);
|
||||
let contents = fs::read_to_string(path.join("tauri.conf.json"))?;
|
||||
|
||||
Ok(serde_json::from_str(&contents).expect("failed to read tauri.conf.json"))
|
||||
serde_json::from_str(&contents).expect("failed to read tauri.conf.json")
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
CONFIG
|
||||
.set(config)
|
||||
.map_err(|_| anyhow::anyhow!("failed to set CONFIG"))?;
|
||||
|
||||
let config = CONFIG.get().unwrap();
|
||||
Ok(config)
|
||||
}
|
||||
|
||||
#[cfg(test)]
|
||||
@@ -328,7 +341,7 @@ mod test {
|
||||
// On Ok, check that the config is the same as the test config.
|
||||
Ok(c) => {
|
||||
println!("{:?}", c);
|
||||
assert_eq!(c, test_config)
|
||||
assert_eq!(c, &test_config)
|
||||
}
|
||||
Err(_) => assert!(false),
|
||||
}
|
||||
|
||||
@@ -1,4 +1,5 @@
|
||||
use crate::config::Config;
|
||||
#[cfg(windows)]
|
||||
use crate::config::get as get_config;
|
||||
#[cfg(windows)]
|
||||
use std::path::MAIN_SEPARATOR;
|
||||
|
||||
@@ -7,16 +8,14 @@ pub struct Notification {
|
||||
body: Option<String>,
|
||||
title: Option<String>,
|
||||
icon: Option<String>,
|
||||
config: Config,
|
||||
}
|
||||
|
||||
impl Notification {
|
||||
pub fn new(config: Config) -> Self {
|
||||
pub fn new() -> Self {
|
||||
Self {
|
||||
body: None,
|
||||
title: None,
|
||||
icon: None,
|
||||
config,
|
||||
}
|
||||
}
|
||||
|
||||
@@ -46,7 +45,7 @@ impl Notification {
|
||||
if let Some(icon) = self.icon {
|
||||
notification.icon(&icon);
|
||||
}
|
||||
#[cfg(windowss)]
|
||||
#[cfg(windows)]
|
||||
{
|
||||
let exe = std::env::current_exe()?;
|
||||
let exe_dir = exe.parent().expect("failed to get exe directory");
|
||||
@@ -55,8 +54,9 @@ impl Notification {
|
||||
if !(curr_dir.ends_with(format!("{S}target{S}debug", S = MAIN_SEPARATOR).as_str())
|
||||
|| curr_dir.ends_with(format!("{S}target{S}release", S = MAIN_SEPARATOR).as_str()))
|
||||
{
|
||||
let identifier = self.config.tauri.bundle.identifier.clone();
|
||||
notification.id(&identifier);
|
||||
let config = get_config()?;
|
||||
let identifier = config.tauri.bundle.identifier.clone();
|
||||
notification.app_id(&identifier);
|
||||
}
|
||||
}
|
||||
notification
|
||||
|
||||
@@ -81,7 +81,7 @@ switch (navigator.platform) {
|
||||
var Dir = {
|
||||
Audio: 1,
|
||||
Cache: 2,
|
||||
Config: 3,
|
||||
Config: 3,
|
||||
Data: 4,
|
||||
LocalData: 5,
|
||||
Desktop: 6,
|
||||
|
||||
@@ -81,7 +81,7 @@ switch (navigator.platform) {
|
||||
var Dir = {
|
||||
Audio: 1,
|
||||
Cache: 2,
|
||||
Config: 3,
|
||||
Config: 3,
|
||||
Data: 4,
|
||||
LocalData: 5,
|
||||
Desktop: 6,
|
||||
|
||||
@@ -12,24 +12,12 @@ use web_view::{builder, Content, WebView};
|
||||
use super::App;
|
||||
#[cfg(feature = "embedded-server")]
|
||||
use crate::api::tcp::{get_available_port, port_is_available};
|
||||
use tauri_api::config::{get, Config};
|
||||
|
||||
#[cfg(feature = "cli")]
|
||||
use tauri_api::cli::get_matches;
|
||||
use tauri_api::config::get;
|
||||
|
||||
// Main entry point function for running the Webview
|
||||
pub(crate) fn run(application: &mut App) -> crate::Result<()> {
|
||||
// get the tauri config struct
|
||||
let config = get()?;
|
||||
|
||||
#[cfg(feature = "cli")]
|
||||
{
|
||||
let matches = get_matches(config.clone());
|
||||
crate::cli::set_matches(matches)?;
|
||||
}
|
||||
|
||||
// setup the content using the config struct depending on the compile target
|
||||
let main_content = setup_content(config.clone())?;
|
||||
let main_content = setup_content()?;
|
||||
|
||||
// setup the server url for the embedded-server
|
||||
#[cfg(feature = "embedded-server")]
|
||||
@@ -44,7 +32,6 @@ pub(crate) fn run(application: &mut App) -> crate::Result<()> {
|
||||
// build the webview
|
||||
let webview = build_webview(
|
||||
application,
|
||||
config,
|
||||
main_content,
|
||||
if application.splashscreen_html().is_some() {
|
||||
Some(Content::Html(
|
||||
@@ -74,12 +61,13 @@ pub(crate) fn run(application: &mut App) -> crate::Result<()> {
|
||||
|
||||
// setup content for dev-server
|
||||
#[cfg(not(any(feature = "embedded-server", feature = "no-server")))]
|
||||
fn setup_content(config: Config) -> crate::Result<Content<String>> {
|
||||
fn setup_content() -> crate::Result<Content<String>> {
|
||||
let config = get()?;
|
||||
if config.build.dev_path.starts_with("http") {
|
||||
Ok(Content::Url(config.build.dev_path))
|
||||
Ok(Content::Url(config.build.dev_path.clone()))
|
||||
} else {
|
||||
let dev_dir = config.build.dev_path;
|
||||
let dev_path = Path::new(&dev_dir).join("index.tauri.html");
|
||||
let dev_dir = &config.build.dev_path;
|
||||
let dev_path = Path::new(dev_dir).join("index.tauri.html");
|
||||
if !dev_path.exists() {
|
||||
panic!(
|
||||
"Couldn't find 'index.tauri.html' inside {}; did you forget to run 'tauri dev'?",
|
||||
@@ -92,16 +80,21 @@ fn setup_content(config: Config) -> crate::Result<Content<String>> {
|
||||
|
||||
// setup content for embedded server
|
||||
#[cfg(feature = "embedded-server")]
|
||||
fn setup_content(config: Config) -> crate::Result<Content<String>> {
|
||||
let (port, valid) = setup_port(config.clone()).expect("Unable to setup Port");
|
||||
let url = setup_server_url(config.clone(), valid, port).expect("Unable to setup URL");
|
||||
fn setup_content() -> crate::Result<Content<String>> {
|
||||
let (port, valid) = setup_port()?;
|
||||
let url = (if valid {
|
||||
setup_server_url(port)
|
||||
} else {
|
||||
Err(anyhow::anyhow!("invalid port"))
|
||||
})
|
||||
.expect("Unable to setup URL");
|
||||
|
||||
Ok(Content::Url(url.to_string()))
|
||||
}
|
||||
|
||||
// setup content for no-server
|
||||
#[cfg(feature = "no-server")]
|
||||
fn setup_content(_: Config) -> crate::Result<Content<String>> {
|
||||
fn setup_content() -> crate::Result<Content<String>> {
|
||||
let dist_dir = match option_env!("TAURI_DIST_DIR") {
|
||||
Some(d) => d.to_string(),
|
||||
None => env::current_dir()?
|
||||
@@ -116,35 +109,33 @@ fn setup_content(_: Config) -> crate::Result<Content<String>> {
|
||||
|
||||
// get the port for the embedded server
|
||||
#[cfg(feature = "embedded-server")]
|
||||
fn setup_port(config: Config) -> Option<(String, bool)> {
|
||||
fn setup_port() -> crate::Result<(String, bool)> {
|
||||
let config = get()?;
|
||||
if config.tauri.embedded_server.port == "random" {
|
||||
match get_available_port() {
|
||||
Some(available_port) => Some((available_port.to_string(), true)),
|
||||
None => Some(("0".to_string(), false)),
|
||||
Some(available_port) => Ok((available_port.to_string(), true)),
|
||||
None => Ok(("0".to_string(), false)),
|
||||
}
|
||||
} else {
|
||||
let port = config.tauri.embedded_server.port;
|
||||
let port = &config.tauri.embedded_server.port;
|
||||
let port_valid = port_is_available(
|
||||
port
|
||||
.parse::<u16>()
|
||||
.expect(&format!("Invalid port {}", port)),
|
||||
);
|
||||
Some((port, port_valid))
|
||||
Ok((port.to_string(), port_valid))
|
||||
}
|
||||
}
|
||||
|
||||
// setup the server url for embedded server
|
||||
#[cfg(feature = "embedded-server")]
|
||||
fn setup_server_url(config: Config, valid: bool, port: String) -> Option<String> {
|
||||
if valid {
|
||||
let mut url = format!("{}:{}", config.tauri.embedded_server.host, port);
|
||||
if !url.starts_with("http") {
|
||||
url = format!("http://{}", url);
|
||||
}
|
||||
Some(url)
|
||||
} else {
|
||||
None
|
||||
fn setup_server_url(port: String) -> crate::Result<String> {
|
||||
let config = get()?;
|
||||
let mut url = format!("{}:{}", config.tauri.embedded_server.host, port);
|
||||
if !url.starts_with("http") {
|
||||
url = format!("http://{}", url);
|
||||
}
|
||||
Ok(url)
|
||||
}
|
||||
|
||||
// spawn the embedded server
|
||||
@@ -186,22 +177,21 @@ fn spawn_updater() -> crate::Result<()> {
|
||||
// build the webview struct
|
||||
fn build_webview(
|
||||
application: &mut App,
|
||||
config: Config,
|
||||
content: Content<String>,
|
||||
splashscreen_content: Option<Content<String>>,
|
||||
) -> crate::Result<WebView<'_, ()>> {
|
||||
let config = get()?;
|
||||
let content_clone = match content {
|
||||
Content::Html(ref html) => Content::Html(html.clone()),
|
||||
Content::Url(ref url) => Content::Url(url.clone()),
|
||||
};
|
||||
let debug = cfg!(debug_assertions);
|
||||
let config_clone = config.clone();
|
||||
// get properties from config struct
|
||||
let width = config.tauri.window.width;
|
||||
let height = config.tauri.window.height;
|
||||
let resizable = config.tauri.window.resizable;
|
||||
let fullscreen = config.tauri.window.fullscreen;
|
||||
let title = config.tauri.window.title.into_boxed_str();
|
||||
let title = config.tauri.window.title.clone().into_boxed_str();
|
||||
|
||||
let has_splashscreen = splashscreen_content.is_some();
|
||||
let mut initialized_splashscreen = false;
|
||||
@@ -229,9 +219,7 @@ fn build_webview(
|
||||
webview.eval(&format!(r#"window.location.href = "{}""#, content_href))?;
|
||||
} else {
|
||||
let handler_error;
|
||||
if let Err(tauri_handle_error) =
|
||||
crate::endpoints::handle(webview, arg, config_clone.clone())
|
||||
{
|
||||
if let Err(tauri_handle_error) = crate::endpoints::handle(webview, arg) {
|
||||
let tauri_handle_error_str = tauri_handle_error.to_string();
|
||||
if tauri_handle_error_str.contains("unknown variant") {
|
||||
let handled_by_app = application.run_invoke_handler(webview, arg);
|
||||
@@ -295,14 +283,13 @@ mod test {
|
||||
#[cfg(not(feature = "embedded-server"))]
|
||||
use std::{env, fs::read_to_string, path::Path};
|
||||
|
||||
fn init_config() -> tauri_api::config::Config {
|
||||
fn init_config() -> &'static tauri_api::config::Config {
|
||||
tauri_api::config::get().expect("unable to setup default config")
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn check_setup_content() {
|
||||
let config = init_config();
|
||||
let _c = config.clone();
|
||||
|
||||
let tauri_dir = match option_env!("TAURI_DIR") {
|
||||
Some(d) => d.to_string(),
|
||||
@@ -313,7 +300,7 @@ mod test {
|
||||
.expect("Unable to convert to normal String"),
|
||||
};
|
||||
env::set_current_dir(tauri_dir).expect("failed to change cwd");
|
||||
let res = super::setup_content(config);
|
||||
let res = super::setup_content();
|
||||
|
||||
#[cfg(feature = "embedded-server")]
|
||||
match res {
|
||||
@@ -342,10 +329,10 @@ mod test {
|
||||
|
||||
#[cfg(not(any(feature = "embedded-server", feature = "no-server")))]
|
||||
match res {
|
||||
Ok(Content::Url(dp)) => assert_eq!(dp, _c.build.dev_path),
|
||||
Ok(Content::Url(dp)) => assert_eq!(dp, config.build.dev_path),
|
||||
Ok(Content::Html(s)) => {
|
||||
let dev_dir = _c.build.dev_path;
|
||||
let dev_path = Path::new(&dev_dir).join("index.tauri.html");
|
||||
let dev_dir = &config.build.dev_path;
|
||||
let dev_path = Path::new(dev_dir).join("index.tauri.html");
|
||||
assert_eq!(
|
||||
s,
|
||||
read_to_string(dev_path).expect("failed to read dev path")
|
||||
@@ -358,11 +345,9 @@ mod test {
|
||||
#[cfg(feature = "embedded-server")]
|
||||
#[test]
|
||||
fn check_setup_port() {
|
||||
let config = init_config();
|
||||
|
||||
let res = super::setup_port(config);
|
||||
let res = super::setup_port();
|
||||
match res {
|
||||
Some((_s, _b)) => assert!(true),
|
||||
Ok((_s, _b)) => assert!(true),
|
||||
_ => assert!(false),
|
||||
}
|
||||
}
|
||||
@@ -372,16 +357,13 @@ mod test {
|
||||
#[cfg(feature = "embedded-server")]
|
||||
#[test]
|
||||
fn check_server_url(port in (any::<u32>().prop_map(|v| v.to_string()))) {
|
||||
let config = init_config();
|
||||
let valid = true;
|
||||
|
||||
let p = port.clone();
|
||||
|
||||
let res = super::setup_server_url(config, valid, port);
|
||||
let res = super::setup_server_url(port);
|
||||
|
||||
match res {
|
||||
Some(url) => assert!(url.contains(&p)),
|
||||
None => assert!(false)
|
||||
Ok(url) => assert!(url.contains(&p)),
|
||||
Err(_) => assert!(false)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,14 +1,8 @@
|
||||
use once_cell::sync::OnceCell;
|
||||
use once_cell::sync::Lazy;
|
||||
use tauri_api::cli::Matches;
|
||||
|
||||
static MATCHES: OnceCell<Matches> = OnceCell::new();
|
||||
pub fn get_matches() -> &'static Option<Matches> {
|
||||
static MATCHES: Lazy<Option<Matches>> = Lazy::new(|| tauri_api::cli::get_matches().ok());
|
||||
|
||||
pub(crate) fn set_matches(matches: Matches) -> crate::Result<()> {
|
||||
MATCHES
|
||||
.set(matches)
|
||||
.map_err(|_| anyhow::anyhow!("failed to set once_cell matches"))
|
||||
}
|
||||
|
||||
pub fn get_matches() -> Option<&'static Matches> {
|
||||
MATCHES.get()
|
||||
&MATCHES
|
||||
}
|
||||
|
||||
@@ -6,15 +6,10 @@ mod salt;
|
||||
|
||||
#[cfg(any(feature = "embedded-server", feature = "no-server"))]
|
||||
use std::path::PathBuf;
|
||||
use tauri_api::config::Config;
|
||||
use web_view::WebView;
|
||||
|
||||
#[allow(unused_variables)]
|
||||
pub(crate) fn handle<T: 'static>(
|
||||
webview: &mut WebView<'_, T>,
|
||||
arg: &str,
|
||||
config: Config,
|
||||
) -> crate::Result<()> {
|
||||
pub(crate) fn handle<T: 'static>(webview: &mut WebView<'_, T>, arg: &str) -> crate::Result<()> {
|
||||
use cmd::Cmd::*;
|
||||
match serde_json::from_str(arg) {
|
||||
Err(e) => Err(e.into()),
|
||||
@@ -199,7 +194,7 @@ pub(crate) fn handle<T: 'static>(
|
||||
callback,
|
||||
error,
|
||||
} => {
|
||||
notification(webview, options, callback, error, config)?;
|
||||
notification(webview, options, callback, error)?;
|
||||
}
|
||||
#[cfg(any(feature = "all-api", feature = "notification"))]
|
||||
IsNotificationPermissionGranted { callback, error } => {
|
||||
@@ -413,12 +408,11 @@ fn notification<T: 'static>(
|
||||
options: cmd::NotificationOptions,
|
||||
callback: String,
|
||||
error: String,
|
||||
config: Config,
|
||||
) -> crate::Result<()> {
|
||||
crate::execute_promise(
|
||||
webview,
|
||||
move || {
|
||||
let mut notification = tauri_api::notification::Notification::new(config);
|
||||
let mut notification = tauri_api::notification::Notification::new();
|
||||
notification.body(options.body);
|
||||
if let Some(title) = options.title {
|
||||
notification.title(title);
|
||||
|
||||
Reference in New Issue
Block a user