feat(tauri) make Config globally available (#681)

This commit is contained in:
Lucas Fernandes Nogueira
2020-06-17 13:05:51 -03:00
committed by GitHub
parent ea74c5cc01
commit d3c53ebf30
9 changed files with 96 additions and 107 deletions

View File

@@ -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"

View File

@@ -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 {

View File

@@ -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),
}

View File

@@ -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

View File

@@ -81,7 +81,7 @@ switch (navigator.platform) {
var Dir = {
Audio: 1,
Cache: 2,
Config: 3,
Config: 3,
Data: 4,
LocalData: 5,
Desktop: 6,

View File

@@ -81,7 +81,7 @@ switch (navigator.platform) {
var Dir = {
Audio: 1,
Cache: 2,
Config: 3,
Config: 3,
Data: 4,
LocalData: 5,
Desktop: 6,

View File

@@ -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)
}
}
}

View File

@@ -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
}

View File

@@ -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);