mirror of
https://github.com/tauri-apps/tauri.git
synced 2024-10-26 18:12:23 +03:00
feat(core): allow swapping the assets implementation (#9141)
This commit is contained in:
parent
db1ea98512
commit
ba0206d8a3
6
.changes/codegen-set-assets.md
Normal file
6
.changes/codegen-set-assets.md
Normal file
@ -0,0 +1,6 @@
|
|||||||
|
---
|
||||||
|
"tauri-macros": patch:feat
|
||||||
|
"tauri-codegen": patch:feat
|
||||||
|
---
|
||||||
|
|
||||||
|
The `Context` codegen now accepts a `assets` input to define a custom `tauri::Assets` implementation.
|
5
.changes/context-assets-unbox.md
Normal file
5
.changes/context-assets-unbox.md
Normal file
@ -0,0 +1,5 @@
|
|||||||
|
---
|
||||||
|
"tauri": patch:breaking
|
||||||
|
---
|
||||||
|
|
||||||
|
`Context::assets` now returns `&dyn Assets` instead of `Box<&dyn Assets>`.
|
5
.changes/context-remove-assets-generics.md
Normal file
5
.changes/context-remove-assets-generics.md
Normal file
@ -0,0 +1,5 @@
|
|||||||
|
---
|
||||||
|
"tauri": patch:breaking
|
||||||
|
---
|
||||||
|
|
||||||
|
The `Context` type no longer uses the `<A: Assets>` generic so the assets implementation can be swapped with `Context::assets_mut`.
|
@ -128,6 +128,7 @@ impl CodegenContext {
|
|||||||
// outside the tauri crate, making the ::tauri root valid.
|
// outside the tauri crate, making the ::tauri root valid.
|
||||||
root: quote::quote!(::tauri),
|
root: quote::quote!(::tauri),
|
||||||
capabilities: self.capabilities,
|
capabilities: self.capabilities,
|
||||||
|
assets: None,
|
||||||
})?;
|
})?;
|
||||||
|
|
||||||
// get the full output file path
|
// get the full output file path
|
||||||
|
@ -12,6 +12,7 @@ use proc_macro2::TokenStream;
|
|||||||
use quote::quote;
|
use quote::quote;
|
||||||
use sha2::{Digest, Sha256};
|
use sha2::{Digest, Sha256};
|
||||||
|
|
||||||
|
use syn::Expr;
|
||||||
use tauri_utils::acl::capability::{Capability, CapabilityFile};
|
use tauri_utils::acl::capability::{Capability, CapabilityFile};
|
||||||
use tauri_utils::acl::manifest::Manifest;
|
use tauri_utils::acl::manifest::Manifest;
|
||||||
use tauri_utils::acl::resolved::Resolved;
|
use tauri_utils::acl::resolved::Resolved;
|
||||||
@ -36,6 +37,8 @@ pub struct ContextData {
|
|||||||
pub root: TokenStream,
|
pub root: TokenStream,
|
||||||
/// Additional capabilities to include.
|
/// Additional capabilities to include.
|
||||||
pub capabilities: Option<Vec<PathBuf>>,
|
pub capabilities: Option<Vec<PathBuf>>,
|
||||||
|
/// The custom assets implementation
|
||||||
|
pub assets: Option<Expr>,
|
||||||
}
|
}
|
||||||
|
|
||||||
fn inject_script_hashes(document: &NodeRef, key: &AssetKey, csp_hashes: &mut CspHashes) {
|
fn inject_script_hashes(document: &NodeRef, key: &AssetKey, csp_hashes: &mut CspHashes) {
|
||||||
@ -132,6 +135,7 @@ pub fn context_codegen(data: ContextData) -> Result<TokenStream, EmbeddedAssetsE
|
|||||||
config_parent,
|
config_parent,
|
||||||
root,
|
root,
|
||||||
capabilities: additional_capabilities,
|
capabilities: additional_capabilities,
|
||||||
|
assets,
|
||||||
} = data;
|
} = data;
|
||||||
|
|
||||||
let target = std::env::var("TARGET")
|
let target = std::env::var("TARGET")
|
||||||
@ -163,10 +167,13 @@ pub fn context_codegen(data: ContextData) -> Result<TokenStream, EmbeddedAssetsE
|
|||||||
options = options.with_csp();
|
options = options.with_csp();
|
||||||
}
|
}
|
||||||
|
|
||||||
let assets = if dev && config.build.dev_url.is_some() {
|
let assets = if let Some(assets) = assets {
|
||||||
Default::default()
|
quote!(#assets)
|
||||||
|
} else if dev && config.build.dev_url.is_some() {
|
||||||
|
let assets = EmbeddedAssets::default();
|
||||||
|
quote!(#assets)
|
||||||
} else {
|
} else {
|
||||||
match &config.build.frontend_dist {
|
let assets = match &config.build.frontend_dist {
|
||||||
Some(url) => match url {
|
Some(url) => match url {
|
||||||
FrontendDist::Url(_url) => Default::default(),
|
FrontendDist::Url(_url) => Default::default(),
|
||||||
FrontendDist::Directory(path) => {
|
FrontendDist::Directory(path) => {
|
||||||
@ -190,7 +197,8 @@ pub fn context_codegen(data: ContextData) -> Result<TokenStream, EmbeddedAssetsE
|
|||||||
_ => unimplemented!(),
|
_ => unimplemented!(),
|
||||||
},
|
},
|
||||||
None => Default::default(),
|
None => Default::default(),
|
||||||
}
|
};
|
||||||
|
quote!(#assets)
|
||||||
};
|
};
|
||||||
|
|
||||||
let out_dir = {
|
let out_dir = {
|
||||||
|
@ -17,6 +17,7 @@ pub(crate) struct ContextItems {
|
|||||||
config_file: PathBuf,
|
config_file: PathBuf,
|
||||||
root: syn::Path,
|
root: syn::Path,
|
||||||
capabilities: Option<Vec<PathBuf>>,
|
capabilities: Option<Vec<PathBuf>>,
|
||||||
|
assets: Option<Expr>,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Parse for ContextItems {
|
impl Parse for ContextItems {
|
||||||
@ -29,6 +30,7 @@ impl Parse for ContextItems {
|
|||||||
|
|
||||||
let mut root = None;
|
let mut root = None;
|
||||||
let mut capabilities = None;
|
let mut capabilities = None;
|
||||||
|
let mut assets = None;
|
||||||
let config_file = input.parse::<LitStr>().ok().map(|raw| {
|
let config_file = input.parse::<LitStr>().ok().map(|raw| {
|
||||||
let _ = input.parse::<Token![,]>();
|
let _ = input.parse::<Token![,]>();
|
||||||
let path = PathBuf::from(raw.value());
|
let path = PathBuf::from(raw.value());
|
||||||
@ -57,32 +59,44 @@ impl Parse for ContextItems {
|
|||||||
root.replace(p);
|
root.replace(p);
|
||||||
}
|
}
|
||||||
Meta::NameValue(v) => {
|
Meta::NameValue(v) => {
|
||||||
if *v.path.require_ident()? == "capabilities" {
|
let ident = v.path.require_ident()?;
|
||||||
if let Expr::Array(array) = v.value {
|
match ident.to_string().as_str() {
|
||||||
capabilities.replace(
|
"capabilities" => {
|
||||||
array
|
if let Expr::Array(array) = v.value {
|
||||||
.elems
|
capabilities.replace(
|
||||||
.into_iter()
|
array
|
||||||
.map(|e| {
|
.elems
|
||||||
if let Expr::Lit(ExprLit {
|
.into_iter()
|
||||||
attrs: _,
|
.map(|e| {
|
||||||
lit: Lit::Str(s),
|
if let Expr::Lit(ExprLit {
|
||||||
}) = e
|
attrs: _,
|
||||||
{
|
lit: Lit::Str(s),
|
||||||
Ok(s.value().into())
|
}) = e
|
||||||
} else {
|
{
|
||||||
Err(syn::Error::new(
|
Ok(s.value().into())
|
||||||
input.span(),
|
} else {
|
||||||
"unexpected expression for capability",
|
Err(syn::Error::new(
|
||||||
))
|
input.span(),
|
||||||
}
|
"unexpected expression for capability",
|
||||||
})
|
))
|
||||||
.collect::<Result<Vec<_>, syn::Error>>()?,
|
}
|
||||||
);
|
})
|
||||||
} else {
|
.collect::<Result<Vec<_>, syn::Error>>()?,
|
||||||
|
);
|
||||||
|
} else {
|
||||||
|
return Err(syn::Error::new(
|
||||||
|
input.span(),
|
||||||
|
"unexpected value for capabilities",
|
||||||
|
));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
"assets" => {
|
||||||
|
assets.replace(v.value);
|
||||||
|
}
|
||||||
|
name => {
|
||||||
return Err(syn::Error::new(
|
return Err(syn::Error::new(
|
||||||
input.span(),
|
input.span(),
|
||||||
"unexpected value for capabilities",
|
format!("unknown attribute {name}"),
|
||||||
));
|
));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -113,6 +127,7 @@ impl Parse for ContextItems {
|
|||||||
}
|
}
|
||||||
}),
|
}),
|
||||||
capabilities,
|
capabilities,
|
||||||
|
assets,
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -126,6 +141,7 @@ pub(crate) fn generate_context(context: ContextItems) -> TokenStream {
|
|||||||
config_parent,
|
config_parent,
|
||||||
root: context.root.to_token_stream(),
|
root: context.root.to_token_stream(),
|
||||||
capabilities: context.capabilities,
|
capabilities: context.capabilities,
|
||||||
|
assets: context.assets,
|
||||||
})
|
})
|
||||||
.and_then(|data| context_codegen(data).map_err(|e| e.to_string()));
|
.and_then(|data| context_codegen(data).map_err(|e| e.to_string()));
|
||||||
|
|
||||||
|
@ -19,7 +19,7 @@ use crate::{
|
|||||||
},
|
},
|
||||||
sealed::{ManagerBase, RuntimeOrDispatch},
|
sealed::{ManagerBase, RuntimeOrDispatch},
|
||||||
utils::config::Config,
|
utils::config::Config,
|
||||||
utils::{assets::Assets, Env},
|
utils::Env,
|
||||||
webview::PageLoadPayload,
|
webview::PageLoadPayload,
|
||||||
Context, DeviceEventFilter, EventLoopMessage, Manager, Monitor, Runtime, Scopes, StateManager,
|
Context, DeviceEventFilter, EventLoopMessage, Manager, Monitor, Runtime, Scopes, StateManager,
|
||||||
Theme, Webview, WebviewWindowBuilder, Window,
|
Theme, Webview, WebviewWindowBuilder, Window,
|
||||||
@ -1581,7 +1581,7 @@ tauri::Builder::default()
|
|||||||
feature = "tracing",
|
feature = "tracing",
|
||||||
tracing::instrument(name = "app::build", skip_all)
|
tracing::instrument(name = "app::build", skip_all)
|
||||||
)]
|
)]
|
||||||
pub fn build<A: Assets>(mut self, context: Context<A>) -> crate::Result<App<R>> {
|
pub fn build(mut self, context: Context) -> crate::Result<App<R>> {
|
||||||
#[cfg(target_os = "macos")]
|
#[cfg(target_os = "macos")]
|
||||||
if self.menu.is_none() && self.enable_macos_default_menu {
|
if self.menu.is_none() && self.enable_macos_default_menu {
|
||||||
self.menu = Some(Box::new(|app_handle| {
|
self.menu = Some(Box::new(|app_handle| {
|
||||||
@ -1749,7 +1749,7 @@ tauri::Builder::default()
|
|||||||
}
|
}
|
||||||
|
|
||||||
/// Runs the configured Tauri application.
|
/// Runs the configured Tauri application.
|
||||||
pub fn run<A: Assets>(self, context: Context<A>) -> crate::Result<()> {
|
pub fn run(self, context: Context) -> crate::Result<()> {
|
||||||
self.build(context)?.run(|_, _| {});
|
self.build(context)?.run(|_, _| {});
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
@ -343,9 +343,9 @@ pub fn dev() -> bool {
|
|||||||
/// # Stability
|
/// # Stability
|
||||||
/// This is the output of the [`generate_context`] macro, and is not considered part of the stable API.
|
/// This is the output of the [`generate_context`] macro, and is not considered part of the stable API.
|
||||||
/// Unless you know what you are doing and are prepared for this type to have breaking changes, do not create it yourself.
|
/// Unless you know what you are doing and are prepared for this type to have breaking changes, do not create it yourself.
|
||||||
pub struct Context<A: Assets> {
|
pub struct Context {
|
||||||
pub(crate) config: Config,
|
pub(crate) config: Config,
|
||||||
pub(crate) assets: Box<A>,
|
pub(crate) assets: Box<dyn Assets>,
|
||||||
pub(crate) default_window_icon: Option<image::Image<'static>>,
|
pub(crate) default_window_icon: Option<image::Image<'static>>,
|
||||||
pub(crate) app_icon: Option<Vec<u8>>,
|
pub(crate) app_icon: Option<Vec<u8>>,
|
||||||
#[cfg(all(desktop, feature = "tray-icon"))]
|
#[cfg(all(desktop, feature = "tray-icon"))]
|
||||||
@ -356,7 +356,7 @@ pub struct Context<A: Assets> {
|
|||||||
pub(crate) runtime_authority: RuntimeAuthority,
|
pub(crate) runtime_authority: RuntimeAuthority,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<A: Assets> fmt::Debug for Context<A> {
|
impl fmt::Debug for Context {
|
||||||
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
|
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
|
||||||
let mut d = f.debug_struct("Context");
|
let mut d = f.debug_struct("Context");
|
||||||
d.field("config", &self.config)
|
d.field("config", &self.config)
|
||||||
@ -372,7 +372,7 @@ impl<A: Assets> fmt::Debug for Context<A> {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<A: Assets> Context<A> {
|
impl Context {
|
||||||
/// The config the application was prepared with.
|
/// The config the application was prepared with.
|
||||||
#[inline(always)]
|
#[inline(always)]
|
||||||
pub fn config(&self) -> &Config {
|
pub fn config(&self) -> &Config {
|
||||||
@ -387,13 +387,13 @@ impl<A: Assets> Context<A> {
|
|||||||
|
|
||||||
/// The assets to be served directly by Tauri.
|
/// The assets to be served directly by Tauri.
|
||||||
#[inline(always)]
|
#[inline(always)]
|
||||||
pub fn assets(&self) -> &A {
|
pub fn assets(&self) -> &dyn Assets {
|
||||||
&self.assets
|
self.assets.as_ref()
|
||||||
}
|
}
|
||||||
|
|
||||||
/// A mutable reference to the assets to be served directly by Tauri.
|
/// A mutable reference to the assets to be served directly by Tauri.
|
||||||
#[inline(always)]
|
#[inline(always)]
|
||||||
pub fn assets_mut(&mut self) -> &mut A {
|
pub fn assets_mut(&mut self) -> &mut Box<dyn Assets> {
|
||||||
&mut self.assets
|
&mut self.assets
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -459,7 +459,7 @@ impl<A: Assets> Context<A> {
|
|||||||
#[allow(clippy::too_many_arguments)]
|
#[allow(clippy::too_many_arguments)]
|
||||||
pub fn new(
|
pub fn new(
|
||||||
config: Config,
|
config: Config,
|
||||||
assets: Box<A>,
|
assets: Box<dyn Assets>,
|
||||||
default_window_icon: Option<image::Image<'static>>,
|
default_window_icon: Option<image::Image<'static>>,
|
||||||
app_icon: Option<Vec<u8>>,
|
app_icon: Option<Vec<u8>>,
|
||||||
package_info: PackageInfo,
|
package_info: PackageInfo,
|
||||||
|
@ -216,7 +216,7 @@ impl<R: Runtime> fmt::Debug for AppManager<R> {
|
|||||||
impl<R: Runtime> AppManager<R> {
|
impl<R: Runtime> AppManager<R> {
|
||||||
#[allow(clippy::too_many_arguments, clippy::type_complexity)]
|
#[allow(clippy::too_many_arguments, clippy::type_complexity)]
|
||||||
pub(crate) fn with_handlers(
|
pub(crate) fn with_handlers(
|
||||||
#[allow(unused_mut)] mut context: Context<impl Assets>,
|
#[allow(unused_mut)] mut context: Context,
|
||||||
plugins: PluginStore<R>,
|
plugins: PluginStore<R>,
|
||||||
invoke_handler: Box<InvokeHandler<R>>,
|
invoke_handler: Box<InvokeHandler<R>>,
|
||||||
on_page_load: Option<Arc<OnPageLoad<R>>>,
|
on_page_load: Option<Arc<OnPageLoad<R>>>,
|
||||||
|
@ -94,7 +94,7 @@ pub fn noop_assets() -> NoopAsset {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/// Creates a new [`crate::Context`] for testing.
|
/// Creates a new [`crate::Context`] for testing.
|
||||||
pub fn mock_context<A: Assets>(assets: A) -> crate::Context<A> {
|
pub fn mock_context<A: Assets>(assets: A) -> crate::Context {
|
||||||
Context {
|
Context {
|
||||||
config: Config {
|
config: Config {
|
||||||
schema: None,
|
schema: None,
|
||||||
|
@ -78,7 +78,7 @@ mod ui {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fn context() -> tauri::Context<tauri::utils::assets::EmbeddedAssets> {
|
fn context() -> tauri::Context {
|
||||||
tauri::generate_context!("../../examples/splashscreen/tauri.conf.json")
|
tauri::generate_context!("../../examples/splashscreen/tauri.conf.json")
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Loading…
Reference in New Issue
Block a user