mirror of
https://github.com/tauri-apps/tauri.git
synced 2026-04-01 10:01:07 +02:00
* feat(core): allow `dev_path`, `dist_dir` as array of paths, fixes #1897 * fix: clippy
This commit is contained in:
committed by
GitHub
parent
cb6c807ac8
commit
6ec54c53b5
7
.changes/dev-path-dist-dir-array.md
Normal file
7
.changes/dev-path-dist-dir-array.md
Normal file
@@ -0,0 +1,7 @@
|
||||
---
|
||||
"tauri": patch
|
||||
"tauri-codegen": patch
|
||||
"tauri-utils": patch
|
||||
---
|
||||
|
||||
Allow `dev_path` and `dist_dir` to be an array of root files and directories to embed.
|
||||
@@ -6,7 +6,7 @@ use crate::embedded_assets::{AssetOptions, EmbeddedAssets, EmbeddedAssetsError};
|
||||
use proc_macro2::TokenStream;
|
||||
use quote::quote;
|
||||
use std::path::PathBuf;
|
||||
use tauri_utils::config::{Config, WindowUrl};
|
||||
use tauri_utils::config::{AppUrl, Config, WindowUrl};
|
||||
|
||||
/// Necessary data needed by [`context_codegen`] to generate code for a Tauri application context.
|
||||
pub struct ContextData {
|
||||
@@ -24,42 +24,45 @@ pub fn context_codegen(data: ContextData) -> Result<TokenStream, EmbeddedAssetsE
|
||||
config_parent,
|
||||
root,
|
||||
} = data;
|
||||
|
||||
let mut options = AssetOptions::new();
|
||||
if let Some(csp) = &config.tauri.security.csp {
|
||||
options = options.csp(csp.clone());
|
||||
}
|
||||
|
||||
let app_url = if dev {
|
||||
&config.build.dev_path
|
||||
} else {
|
||||
&config.build.dist_dir
|
||||
};
|
||||
let assets_path = match app_url {
|
||||
WindowUrl::External(_) => None,
|
||||
WindowUrl::App(path) => {
|
||||
if path.components().count() == 0 {
|
||||
panic!(
|
||||
"The `{}` configuration cannot be empty",
|
||||
if dev { "devPath" } else { "distDir" }
|
||||
)
|
||||
}
|
||||
let assets_path = config_parent.join(path);
|
||||
if !assets_path.exists() {
|
||||
panic!(
|
||||
"The `{}` configuration is set to `{:?}` but this path doesn't exist",
|
||||
if dev { "devPath" } else { "distDir" },
|
||||
path
|
||||
)
|
||||
}
|
||||
Some(assets_path)
|
||||
}
|
||||
_ => unimplemented!(),
|
||||
};
|
||||
|
||||
// generate the assets inside the dist dir into a perfect hash function
|
||||
let assets = if let Some(assets_path) = assets_path {
|
||||
let mut options = AssetOptions::new();
|
||||
if let Some(csp) = &config.tauri.security.csp {
|
||||
options = options.csp(csp.clone());
|
||||
}
|
||||
EmbeddedAssets::new(&assets_path, options)?
|
||||
} else {
|
||||
Default::default()
|
||||
let assets = match app_url {
|
||||
AppUrl::Url(url) => match url {
|
||||
WindowUrl::External(_) => Default::default(),
|
||||
WindowUrl::App(path) => {
|
||||
if path.components().count() == 0 {
|
||||
panic!(
|
||||
"The `{}` configuration cannot be empty",
|
||||
if dev { "devPath" } else { "distDir" }
|
||||
)
|
||||
}
|
||||
let assets_path = config_parent.join(path);
|
||||
if !assets_path.exists() {
|
||||
panic!(
|
||||
"The `{}` configuration is set to `{:?}` but this path doesn't exist",
|
||||
if dev { "devPath" } else { "distDir" },
|
||||
path
|
||||
)
|
||||
}
|
||||
EmbeddedAssets::new(&assets_path, options)?
|
||||
}
|
||||
_ => unimplemented!(),
|
||||
},
|
||||
AppUrl::Files(files) => EmbeddedAssets::load_paths(
|
||||
files.iter().map(|p| config_parent.join(p)).collect(),
|
||||
options,
|
||||
)?,
|
||||
_ => unimplemented!(),
|
||||
};
|
||||
|
||||
// handle default window icons for Windows targets
|
||||
|
||||
@@ -106,6 +106,50 @@ impl EmbeddedAssets {
|
||||
.map(Self)
|
||||
}
|
||||
|
||||
/// Compress a list of files and directories.
|
||||
pub fn load_paths(
|
||||
paths: Vec<PathBuf>,
|
||||
options: AssetOptions,
|
||||
) -> Result<Self, EmbeddedAssetsError> {
|
||||
Ok(Self(
|
||||
paths
|
||||
.iter()
|
||||
.map(|path| {
|
||||
let is_file = path.is_file();
|
||||
WalkDir::new(&path)
|
||||
.follow_links(true)
|
||||
.into_iter()
|
||||
.filter_map(|entry| {
|
||||
match entry {
|
||||
// we only serve files, not directory listings
|
||||
Ok(entry) if entry.file_type().is_dir() => None,
|
||||
|
||||
// compress all files encountered
|
||||
Ok(entry) => Some(Self::compress_file(
|
||||
if is_file {
|
||||
path.parent().unwrap()
|
||||
} else {
|
||||
path
|
||||
},
|
||||
entry.path(),
|
||||
&options,
|
||||
)),
|
||||
|
||||
// pass down error through filter to fail when encountering any error
|
||||
Err(error) => Some(Err(EmbeddedAssetsError::Walkdir {
|
||||
path: path.to_path_buf(),
|
||||
error,
|
||||
})),
|
||||
}
|
||||
})
|
||||
.collect::<Result<Vec<Asset>, _>>()
|
||||
})
|
||||
.flatten()
|
||||
.flatten()
|
||||
.collect::<_>(),
|
||||
))
|
||||
}
|
||||
|
||||
/// Use highest compression level for release, the fastest one for everything else
|
||||
fn compression_level() -> i32 {
|
||||
let levels = zstd::compression_level_range();
|
||||
|
||||
@@ -393,27 +393,40 @@ impl Default for TauriConfig {
|
||||
}
|
||||
}
|
||||
|
||||
/// The `dev_path` and `dist_dir` options.
|
||||
#[derive(PartialEq, Debug, Clone, Deserialize)]
|
||||
#[serde(untagged)]
|
||||
#[non_exhaustive]
|
||||
pub enum AppUrl {
|
||||
/// A url or file path.
|
||||
Url(WindowUrl),
|
||||
/// An array of files.
|
||||
Files(Vec<PathBuf>),
|
||||
}
|
||||
|
||||
/// The Build configuration object.
|
||||
#[derive(PartialEq, Deserialize, Debug)]
|
||||
#[serde(rename_all = "camelCase")]
|
||||
pub struct BuildConfig {
|
||||
/// the devPath config.
|
||||
#[serde(default = "default_dev_path")]
|
||||
pub dev_path: WindowUrl,
|
||||
pub dev_path: AppUrl,
|
||||
/// the dist config.
|
||||
#[serde(default = "default_dist_path")]
|
||||
pub dist_dir: WindowUrl,
|
||||
pub dist_dir: AppUrl,
|
||||
/// Whether we should inject the Tauri API on `window.__TAURI__` or not.
|
||||
#[serde(default)]
|
||||
pub with_global_tauri: bool,
|
||||
}
|
||||
|
||||
fn default_dev_path() -> WindowUrl {
|
||||
WindowUrl::External(Url::parse("http://localhost:8080").unwrap())
|
||||
fn default_dev_path() -> AppUrl {
|
||||
AppUrl::Url(WindowUrl::External(
|
||||
Url::parse("http://localhost:8080").unwrap(),
|
||||
))
|
||||
}
|
||||
|
||||
fn default_dist_path() -> WindowUrl {
|
||||
WindowUrl::App("../dist".into())
|
||||
fn default_dist_path() -> AppUrl {
|
||||
AppUrl::Url(WindowUrl::App("../dist".into()))
|
||||
}
|
||||
|
||||
impl Default for BuildConfig {
|
||||
@@ -465,7 +478,7 @@ pub struct PluginConfig(pub HashMap<String, JsonValue>);
|
||||
/// application using tauri while only parsing it once (in the build script).
|
||||
#[cfg(feature = "build")]
|
||||
mod build {
|
||||
use std::convert::identity;
|
||||
use std::{convert::identity, path::Path};
|
||||
|
||||
use proc_macro2::TokenStream;
|
||||
use quote::{quote, ToTokens, TokenStreamExt};
|
||||
@@ -511,6 +524,15 @@ mod build {
|
||||
quote! { vec![#(#items),*] }
|
||||
}
|
||||
|
||||
/// Create a `PathBuf` constructor `TokenStream`.
|
||||
///
|
||||
/// e.g. `"Hello World" -> String::from("Hello World").
|
||||
/// This takes a `&String` to reduce casting all the `&String` -> `&str` manually.
|
||||
fn path_buf_lit(s: impl AsRef<Path>) -> TokenStream {
|
||||
let s = s.as_ref().to_string_lossy().into_owned();
|
||||
quote! { ::std::path::PathBuf::from(#s) }
|
||||
}
|
||||
|
||||
/// Create a map constructor, mapping keys and values with other `TokenStream`s.
|
||||
///
|
||||
/// This function is pretty generic because the types of keys AND values get transformed.
|
||||
@@ -612,8 +634,8 @@ mod build {
|
||||
|
||||
tokens.append_all(match self {
|
||||
Self::App(path) => {
|
||||
let path = path.to_string_lossy().to_string();
|
||||
quote! { #prefix::App(::std::path::PathBuf::from(#path)) }
|
||||
let path = path_buf_lit(&path);
|
||||
quote! { #prefix::App(#path) }
|
||||
}
|
||||
Self::External(url) => {
|
||||
let url = url.as_str();
|
||||
@@ -779,6 +801,22 @@ mod build {
|
||||
}
|
||||
}
|
||||
|
||||
impl ToTokens for AppUrl {
|
||||
fn to_tokens(&self, tokens: &mut TokenStream) {
|
||||
let prefix = quote! { ::tauri::api::config::AppUrl };
|
||||
|
||||
tokens.append_all(match self {
|
||||
Self::Url(url) => {
|
||||
quote! { #prefix::Url(#url) }
|
||||
}
|
||||
Self::Files(files) => {
|
||||
let files = vec_lit(files, path_buf_lit);
|
||||
quote! { #prefix::Files(#files) }
|
||||
}
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
impl ToTokens for BuildConfig {
|
||||
fn to_tokens(&self, tokens: &mut TokenStream) {
|
||||
let dev_path = &self.dev_path;
|
||||
@@ -810,8 +848,7 @@ mod build {
|
||||
|
||||
impl ToTokens for SystemTrayConfig {
|
||||
fn to_tokens(&self, tokens: &mut TokenStream) {
|
||||
let icon_path = self.icon_path.to_string_lossy().to_string();
|
||||
let icon_path = quote! { ::std::path::PathBuf::from(#icon_path) };
|
||||
let icon_path = path_buf_lit(&self.icon_path);
|
||||
literal_struct!(tokens, SystemTrayConfig, icon_path);
|
||||
}
|
||||
}
|
||||
@@ -936,8 +973,10 @@ mod test {
|
||||
|
||||
// create a build config
|
||||
let build = BuildConfig {
|
||||
dev_path: WindowUrl::External(Url::parse("http://localhost:8080").unwrap()),
|
||||
dist_dir: WindowUrl::App("../dist".into()),
|
||||
dev_path: AppUrl::Url(WindowUrl::External(
|
||||
Url::parse("http://localhost:8080").unwrap(),
|
||||
)),
|
||||
dist_dir: AppUrl::Url(WindowUrl::App("../dist".into())),
|
||||
with_global_tauri: false,
|
||||
};
|
||||
|
||||
@@ -948,7 +987,9 @@ mod test {
|
||||
assert_eq!(d_updater, tauri.updater);
|
||||
assert_eq!(
|
||||
d_path,
|
||||
WindowUrl::External(Url::parse("http://localhost:8080").unwrap())
|
||||
AppUrl::Url(WindowUrl::External(
|
||||
Url::parse("http://localhost:8080").unwrap()
|
||||
))
|
||||
);
|
||||
assert_eq!(d_title, tauri.windows[0].title);
|
||||
assert_eq!(d_windows, tauri.windows);
|
||||
|
||||
@@ -8,7 +8,7 @@
|
||||
use crate::{
|
||||
api::{
|
||||
assets::Assets,
|
||||
config::{Config, WindowUrl},
|
||||
config::{AppUrl, Config, WindowUrl},
|
||||
path::{resolve_path, BaseDirectory},
|
||||
PackageInfo,
|
||||
},
|
||||
@@ -282,7 +282,7 @@ impl<P: Params> WindowManager<P> {
|
||||
#[cfg(dev)]
|
||||
fn get_url(&self) -> String {
|
||||
match &self.inner.config.build.dev_path {
|
||||
WindowUrl::External(url) => url.to_string(),
|
||||
AppUrl::Url(WindowUrl::External(url)) => url.to_string(),
|
||||
_ => "tauri://localhost".into(),
|
||||
}
|
||||
}
|
||||
@@ -290,7 +290,7 @@ impl<P: Params> WindowManager<P> {
|
||||
#[cfg(custom_protocol)]
|
||||
fn get_url(&self) -> String {
|
||||
match &self.inner.config.build.dist_dir {
|
||||
WindowUrl::External(url) => url.to_string(),
|
||||
AppUrl::Url(WindowUrl::External(url)) => url.to_string(),
|
||||
_ => "tauri://localhost".into(),
|
||||
}
|
||||
}
|
||||
|
||||
@@ -3,7 +3,6 @@
|
||||
"distDir": "../dist",
|
||||
"devPath": "http://localhost:4000"
|
||||
},
|
||||
"ctx": {},
|
||||
"tauri": {
|
||||
"bundle": {
|
||||
"identifier": "studio.tauri.example",
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
{
|
||||
"build": {
|
||||
"distDir": "../public",
|
||||
"devPath": "../public",
|
||||
"distDir": ["../index.html"],
|
||||
"devPath": ["../index.html"],
|
||||
"beforeDevCommand": "",
|
||||
"beforeBuildCommand": ""
|
||||
},
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
{
|
||||
"build": {
|
||||
"distDir": "../public",
|
||||
"devPath": "../public",
|
||||
"distDir": ["../index.html"],
|
||||
"devPath": ["../index.html"],
|
||||
"beforeDevCommand": "",
|
||||
"beforeBuildCommand": ""
|
||||
},
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
{
|
||||
"build": {
|
||||
"distDir": "../dist",
|
||||
"devPath": "../dist",
|
||||
"distDir": ["../index.html"],
|
||||
"devPath": ["../index.html"],
|
||||
"withGlobalTauri": true
|
||||
},
|
||||
"tauri": {
|
||||
@@ -45,4 +45,4 @@
|
||||
"active": false
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,7 +1,7 @@
|
||||
{
|
||||
"build": {
|
||||
"distDir": "../public",
|
||||
"devPath": "../public",
|
||||
"distDir": ["../index.html"],
|
||||
"devPath": ["../index.html"],
|
||||
"beforeDevCommand": "",
|
||||
"beforeBuildCommand": ""
|
||||
},
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
{
|
||||
"build": {
|
||||
"distDir": "../public",
|
||||
"devPath": "../public",
|
||||
"distDir": ["../index.html"],
|
||||
"devPath": ["../index.html"],
|
||||
"beforeDevCommand": "",
|
||||
"beforeBuildCommand": ""
|
||||
},
|
||||
|
||||
@@ -1,329 +0,0 @@
|
||||
// polyfills
|
||||
if (!String.prototype.startsWith) {
|
||||
String.prototype.startsWith = function (searchString, position) {
|
||||
position = position || 0;
|
||||
return this.substr(position, searchString.length) === searchString;
|
||||
};
|
||||
}
|
||||
|
||||
(function () {
|
||||
function s4() {
|
||||
return Math.floor((1 + Math.random()) * 0x10000)
|
||||
.toString(16)
|
||||
.substring(1);
|
||||
}
|
||||
|
||||
var uid = function () {
|
||||
return (
|
||||
s4() +
|
||||
s4() +
|
||||
"-" +
|
||||
s4() +
|
||||
"-" +
|
||||
s4() +
|
||||
"-" +
|
||||
s4() +
|
||||
"-" +
|
||||
s4() +
|
||||
s4() +
|
||||
s4()
|
||||
);
|
||||
};
|
||||
|
||||
function ownKeys(object, enumerableOnly) {
|
||||
var keys = Object.keys(object);
|
||||
if (Object.getOwnPropertySymbols) {
|
||||
var symbols = Object.getOwnPropertySymbols(object);
|
||||
if (enumerableOnly)
|
||||
symbols = symbols.filter(function (sym) {
|
||||
return Object.getOwnPropertyDescriptor(object, sym).enumerable;
|
||||
});
|
||||
keys.push.apply(keys, symbols);
|
||||
}
|
||||
return keys;
|
||||
}
|
||||
|
||||
function _objectSpread(target) {
|
||||
for (var i = 1; i < arguments.length; i++) {
|
||||
var source = arguments[i] != null ? arguments[i] : {};
|
||||
if (i % 2) {
|
||||
ownKeys(source, true).forEach(function (key) {
|
||||
_defineProperty(target, key, source[key]);
|
||||
});
|
||||
} else if (Object.getOwnPropertyDescriptors) {
|
||||
Object.defineProperties(
|
||||
target,
|
||||
Object.getOwnPropertyDescriptors(source)
|
||||
);
|
||||
} else {
|
||||
ownKeys(source).forEach(function (key) {
|
||||
Object.defineProperty(
|
||||
target,
|
||||
key,
|
||||
Object.getOwnPropertyDescriptor(source, key)
|
||||
);
|
||||
});
|
||||
}
|
||||
}
|
||||
return target;
|
||||
}
|
||||
|
||||
function _defineProperty(obj, key, value) {
|
||||
if (key in obj) {
|
||||
Object.defineProperty(obj, key, {
|
||||
value: value,
|
||||
enumerable: true,
|
||||
configurable: true,
|
||||
writable: true,
|
||||
});
|
||||
} else {
|
||||
obj[key] = value;
|
||||
}
|
||||
return obj;
|
||||
}
|
||||
|
||||
if (!window.__TAURI__) {
|
||||
window.__TAURI__ = {};
|
||||
}
|
||||
|
||||
window.__TAURI__.transformCallback = function transformCallback(
|
||||
callback,
|
||||
once
|
||||
) {
|
||||
var identifier = uid();
|
||||
|
||||
window[identifier] = function (result) {
|
||||
if (once) {
|
||||
delete window[identifier];
|
||||
}
|
||||
|
||||
return callback && callback(result);
|
||||
};
|
||||
|
||||
return identifier;
|
||||
};
|
||||
|
||||
window.__TAURI__.invoke = function invoke(cmd, args = {}) {
|
||||
var _this = this;
|
||||
|
||||
return new Promise(function (resolve, reject) {
|
||||
var callback = _this.transformCallback(function (r) {
|
||||
resolve(r);
|
||||
delete window[error];
|
||||
}, true);
|
||||
var error = _this.transformCallback(function (e) {
|
||||
reject(e);
|
||||
delete window[callback];
|
||||
}, true);
|
||||
|
||||
if (typeof cmd === "string") {
|
||||
args.cmd = cmd;
|
||||
} else if (typeof cmd === "object") {
|
||||
args = cmd;
|
||||
} else {
|
||||
return reject(new Error("Invalid argument type."));
|
||||
}
|
||||
|
||||
if (window.rpc) {
|
||||
window.rpc.notify(
|
||||
cmd,
|
||||
_objectSpread(
|
||||
{
|
||||
callback: callback,
|
||||
error: error,
|
||||
},
|
||||
args
|
||||
)
|
||||
);
|
||||
} else {
|
||||
window.addEventListener("DOMContentLoaded", function () {
|
||||
window.rpc.notify(
|
||||
cmd,
|
||||
_objectSpread(
|
||||
{
|
||||
callback: callback,
|
||||
error: error,
|
||||
},
|
||||
args
|
||||
)
|
||||
);
|
||||
});
|
||||
}
|
||||
});
|
||||
};
|
||||
|
||||
// open <a href="..."> links with the Tauri API
|
||||
function __openLinks() {
|
||||
document.querySelector("body").addEventListener(
|
||||
"click",
|
||||
function (e) {
|
||||
var target = e.target;
|
||||
while (target != null) {
|
||||
if (
|
||||
target.matches ? target.matches("a") : target.msMatchesSelector("a")
|
||||
) {
|
||||
if (
|
||||
target.href &&
|
||||
target.href.startsWith("http") &&
|
||||
target.target === "_blank"
|
||||
) {
|
||||
window.__TAURI__.invoke('tauri', {
|
||||
__tauriModule: "Shell",
|
||||
message: {
|
||||
cmd: "open",
|
||||
uri: target.href,
|
||||
},
|
||||
});
|
||||
e.preventDefault();
|
||||
}
|
||||
break;
|
||||
}
|
||||
target = target.parentElement;
|
||||
}
|
||||
},
|
||||
true
|
||||
);
|
||||
}
|
||||
|
||||
if (
|
||||
document.readyState === "complete" ||
|
||||
document.readyState === "interactive"
|
||||
) {
|
||||
__openLinks();
|
||||
} else {
|
||||
window.addEventListener(
|
||||
"DOMContentLoaded",
|
||||
function () {
|
||||
__openLinks();
|
||||
},
|
||||
true
|
||||
);
|
||||
}
|
||||
|
||||
window.__TAURI__.invoke('tauri', {
|
||||
__tauriModule: "Event",
|
||||
message: {
|
||||
cmd: "listen",
|
||||
event: "tauri://window-created",
|
||||
handler: window.__TAURI__.transformCallback(function (event) {
|
||||
if (event.payload) {
|
||||
var windowLabel = event.payload.label;
|
||||
window.__TAURI__.__windows.push({ label: windowLabel });
|
||||
}
|
||||
}),
|
||||
},
|
||||
});
|
||||
|
||||
let permissionSettable = false;
|
||||
let permissionValue = "default";
|
||||
|
||||
function isPermissionGranted() {
|
||||
if (window.Notification.permission !== "default") {
|
||||
return Promise.resolve(window.Notification.permission === "granted");
|
||||
}
|
||||
return window.__TAURI__.invoke('tauri', {
|
||||
__tauriModule: "Notification",
|
||||
message: {
|
||||
cmd: "isNotificationPermissionGranted",
|
||||
},
|
||||
});
|
||||
}
|
||||
|
||||
function setNotificationPermission(value) {
|
||||
permissionSettable = true;
|
||||
window.Notification.permission = value;
|
||||
permissionSettable = false;
|
||||
}
|
||||
|
||||
function requestPermission() {
|
||||
return window.__TAURI__
|
||||
.invoke('tauri', {
|
||||
__tauriModule: "Notification",
|
||||
mainThread: true,
|
||||
message: {
|
||||
cmd: "requestNotificationPermission",
|
||||
},
|
||||
})
|
||||
.then(function (permission) {
|
||||
setNotificationPermission(permission);
|
||||
return permission;
|
||||
});
|
||||
}
|
||||
|
||||
function sendNotification(options) {
|
||||
if (typeof options === "object") {
|
||||
Object.freeze(options);
|
||||
}
|
||||
|
||||
isPermissionGranted().then(function (permission) {
|
||||
if (permission) {
|
||||
return window.__TAURI__.invoke('tauri', {
|
||||
__tauriModule: "Notification",
|
||||
message: {
|
||||
cmd: "notification",
|
||||
options:
|
||||
typeof options === "string"
|
||||
? {
|
||||
title: options,
|
||||
}
|
||||
: options,
|
||||
},
|
||||
});
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
window.Notification = function (title, options) {
|
||||
var opts = options || {};
|
||||
sendNotification(
|
||||
Object.assign(opts, {
|
||||
title: title,
|
||||
})
|
||||
);
|
||||
};
|
||||
|
||||
window.Notification.requestPermission = requestPermission;
|
||||
|
||||
Object.defineProperty(window.Notification, "permission", {
|
||||
enumerable: true,
|
||||
get: function () {
|
||||
return permissionValue;
|
||||
},
|
||||
set: function (v) {
|
||||
if (!permissionSettable) {
|
||||
throw new Error("Readonly property");
|
||||
}
|
||||
permissionValue = v;
|
||||
},
|
||||
});
|
||||
|
||||
isPermissionGranted().then(function (response) {
|
||||
if (response === null) {
|
||||
setNotificationPermission("default");
|
||||
} else {
|
||||
setNotificationPermission(response ? "granted" : "denied");
|
||||
}
|
||||
});
|
||||
|
||||
window.alert = function (message) {
|
||||
window.__TAURI__.invoke('tauri', {
|
||||
__tauriModule: "Dialog",
|
||||
mainThread: true,
|
||||
message: {
|
||||
cmd: "messageDialog",
|
||||
message: message,
|
||||
},
|
||||
});
|
||||
};
|
||||
|
||||
window.confirm = function (message) {
|
||||
return window.__TAURI__.invoke('tauri', {
|
||||
__tauriModule: "Dialog",
|
||||
mainThread: true,
|
||||
message: {
|
||||
cmd: "askDialog",
|
||||
message: message,
|
||||
},
|
||||
});
|
||||
};
|
||||
})();
|
||||
@@ -1,7 +1,7 @@
|
||||
{
|
||||
"build": {
|
||||
"distDir": "../public",
|
||||
"devPath": "../public",
|
||||
"distDir": ["../index.html"],
|
||||
"devPath": ["../index.html"],
|
||||
"beforeDevCommand": "",
|
||||
"beforeBuildCommand": ""
|
||||
},
|
||||
|
||||
@@ -590,6 +590,25 @@ fn default_dialog() -> Option<bool> {
|
||||
Some(true)
|
||||
}
|
||||
|
||||
/// The `dev_path` and `dist_dir` options.
|
||||
#[derive(Debug, PartialEq, Clone, Deserialize, Serialize, JsonSchema)]
|
||||
#[serde(untagged, deny_unknown_fields)]
|
||||
pub enum AppUrl {
|
||||
/// The app's external URL, or the path to the directory containing the app assets.
|
||||
Url(String),
|
||||
/// An array of files to embed on the app.
|
||||
Files(Vec<PathBuf>),
|
||||
}
|
||||
|
||||
impl std::fmt::Display for AppUrl {
|
||||
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
|
||||
match self {
|
||||
Self::Url(url) => write!(f, "{}", url),
|
||||
Self::Files(files) => write!(f, "{}", serde_json::to_string(files).unwrap()),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// The Build configuration object.
|
||||
#[skip_serializing_none]
|
||||
#[derive(Debug, PartialEq, Clone, Deserialize, Serialize, JsonSchema)]
|
||||
@@ -597,12 +616,12 @@ fn default_dialog() -> Option<bool> {
|
||||
pub struct BuildConfig {
|
||||
/// The binary used to build and run the application.
|
||||
pub runner: Option<String>,
|
||||
/// the app's dev server URL, or the path to the directory containing an index.html file
|
||||
/// The path or URL to use on development.
|
||||
#[serde(default = "default_dev_path")]
|
||||
pub dev_path: String,
|
||||
pub dev_path: AppUrl,
|
||||
/// the path to the app's dist dir. This path must contain your index.html file.
|
||||
#[serde(default = "default_dist_dir")]
|
||||
pub dist_dir: String,
|
||||
pub dist_dir: AppUrl,
|
||||
/// a shell command to run before `tauri dev` kicks in
|
||||
pub before_dev_command: Option<String>,
|
||||
/// a shell command to run before `tauri build` kicks in
|
||||
@@ -614,12 +633,12 @@ pub struct BuildConfig {
|
||||
pub with_global_tauri: bool,
|
||||
}
|
||||
|
||||
fn default_dev_path() -> String {
|
||||
"".to_string()
|
||||
fn default_dev_path() -> AppUrl {
|
||||
AppUrl::Url("".to_string())
|
||||
}
|
||||
|
||||
fn default_dist_dir() -> String {
|
||||
"../dist".to_string()
|
||||
fn default_dist_dir() -> AppUrl {
|
||||
AppUrl::Url("../dist".to_string())
|
||||
}
|
||||
|
||||
type JsonObject = HashMap<String, JsonValue>;
|
||||
|
||||
@@ -206,6 +206,22 @@
|
||||
},
|
||||
"additionalProperties": false
|
||||
},
|
||||
"AppUrl": {
|
||||
"description": "The `dev_path` and `dist_dir` options.",
|
||||
"anyOf": [
|
||||
{
|
||||
"description": "The app's external URL, or the path to the directory containing the app assets.",
|
||||
"type": "string"
|
||||
},
|
||||
{
|
||||
"description": "An array of files to embed on the app.",
|
||||
"type": "array",
|
||||
"items": {
|
||||
"type": "string"
|
||||
}
|
||||
}
|
||||
]
|
||||
},
|
||||
"BuildConfig": {
|
||||
"description": "The Build configuration object.",
|
||||
"type": "object",
|
||||
@@ -225,14 +241,22 @@
|
||||
]
|
||||
},
|
||||
"devPath": {
|
||||
"description": "the app's dev server URL, or the path to the directory containing an index.html file",
|
||||
"description": "The path or URL to use on development.",
|
||||
"default": "",
|
||||
"type": "string"
|
||||
"allOf": [
|
||||
{
|
||||
"$ref": "#/definitions/AppUrl"
|
||||
}
|
||||
]
|
||||
},
|
||||
"distDir": {
|
||||
"description": "the path to the app's dist dir. This path must contain your index.html file.",
|
||||
"default": "../dist",
|
||||
"type": "string"
|
||||
"allOf": [
|
||||
{
|
||||
"$ref": "#/definitions/AppUrl"
|
||||
}
|
||||
]
|
||||
},
|
||||
"features": {
|
||||
"description": "features passed to `cargo` commands",
|
||||
|
||||
@@ -7,7 +7,7 @@ use tauri_bundler::bundle::{bundle_project, PackageType, SettingsBuilder};
|
||||
|
||||
use crate::helpers::{
|
||||
app_paths::{app_dir, tauri_dir},
|
||||
config::get as get_config,
|
||||
config::{get as get_config, AppUrl},
|
||||
execute_with_output,
|
||||
manifest::rewrite_manifest,
|
||||
updater_signature::sign_file_from_env_variables,
|
||||
@@ -103,12 +103,14 @@ impl Build {
|
||||
}
|
||||
}
|
||||
|
||||
let web_asset_path = PathBuf::from(&config_.build.dist_dir);
|
||||
if !web_asset_path.exists() {
|
||||
return Err(anyhow::anyhow!(
|
||||
"Unable to find your web assets, did you forget to build your web app? Your distDir is set to \"{:?}\".",
|
||||
web_asset_path
|
||||
));
|
||||
if let AppUrl::Url(url) = &config_.build.dist_dir {
|
||||
let web_asset_path = PathBuf::from(url);
|
||||
if !web_asset_path.exists() {
|
||||
return Err(anyhow::anyhow!(
|
||||
"Unable to find your web assets, did you forget to build your web app? Your distDir is set to \"{:?}\".",
|
||||
web_asset_path
|
||||
));
|
||||
}
|
||||
}
|
||||
|
||||
let runner_from_config = config_.build.runner.clone();
|
||||
|
||||
@@ -545,10 +545,10 @@ impl Info {
|
||||
})
|
||||
.display();
|
||||
InfoBlock::new("distDir")
|
||||
.value(config.build.dist_dir.clone())
|
||||
.value(config.build.dist_dir.to_string())
|
||||
.display();
|
||||
InfoBlock::new("devPath")
|
||||
.value(config.build.dev_path.clone())
|
||||
.value(config.build.dev_path.to_string())
|
||||
.display();
|
||||
}
|
||||
if let Ok(package_json) = read_to_string(app_dir.join("package.json")) {
|
||||
|
||||
Reference in New Issue
Block a user