mirror of
https://github.com/tauri-apps/tauri.git
synced 2026-01-31 00:35:19 +01:00
ensure CEF is installed (CLI)
This commit is contained in:
@@ -171,6 +171,12 @@
|
||||
"manager": "rust",
|
||||
"dependencies": ["tauri-utils", "tauri-runtime"]
|
||||
},
|
||||
"tauri-runtime-cef": {
|
||||
"path": "./crates/tauri-runtime-cef",
|
||||
"manager": "rust",
|
||||
"dependencies": ["tauri-utils", "tauri-runtime"],
|
||||
"postversion": "node ../../.scripts/ci/sync-cli-metadata.js ${ pkg.pkg } ${ release.type }"
|
||||
},
|
||||
"tauri-codegen": {
|
||||
"path": "./crates/tauri-codegen",
|
||||
"manager": "rust",
|
||||
|
||||
@@ -59,12 +59,43 @@ const inc = (version) => {
|
||||
// read file into js object
|
||||
const metadata = JSON.parse(readFileSync(filePath, 'utf-8'))
|
||||
|
||||
// Extract CEF version from tauri-runtime-cef/Cargo.toml if it exists
|
||||
// This runs whenever tauri-runtime-cef version is bumped
|
||||
if (packageNickname === 'tauri-runtime-cef') {
|
||||
try {
|
||||
const cargoLockPath = resolve(__dirname, '../../Cargo.lock')
|
||||
const cargoLock = readFileSync(cargoLockPath, 'utf-8')
|
||||
// Find the [package] section for "cef"
|
||||
// e.g.:
|
||||
// [[package]]
|
||||
// name = "cef"
|
||||
// version = "141.6.0+141.0.11"
|
||||
const pkgRegex =
|
||||
/\[\[package\]\][^\[]+?name\s*=\s*"cef"[^\[]+?version\s*=\s*"([^"]+)"/m
|
||||
const match = cargoLock.match(pkgRegex)
|
||||
if (match && match[1]) {
|
||||
const cefVersion = match[1]
|
||||
metadata.cef = cefVersion
|
||||
console.log(`Extracted CEF version ${cefVersion} from Cargo.lock`)
|
||||
} else {
|
||||
throw new Error('Could not find cef package and version in Cargo.lock')
|
||||
}
|
||||
} catch (error) {
|
||||
throw new Error(
|
||||
`Failed to extract CEF version from Cargo.lock: ${error.message}`
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
// set field version
|
||||
let version
|
||||
if (packageNickname === '@tauri-apps/cli') {
|
||||
version = inc(metadata['cli.js'].version)
|
||||
metadata['cli.js'].version = version
|
||||
} else {
|
||||
} else if (
|
||||
packageNickname
|
||||
!== 'tauri-runtime-cef' /* for cef we only update the cef version */
|
||||
) {
|
||||
version = inc(metadata[packageNickname])
|
||||
metadata[packageNickname] = version
|
||||
}
|
||||
|
||||
22
Cargo.lock
generated
22
Cargo.lock
generated
@@ -1188,7 +1188,7 @@ source = "git+https://github.com/tauri-apps/cef-rs?branch=fix/interface-cast#6c3
|
||||
dependencies = [
|
||||
"anyhow",
|
||||
"cmake",
|
||||
"download-cef",
|
||||
"download-cef 2.2.0 (git+https://github.com/tauri-apps/cef-rs?branch=fix/interface-cast)",
|
||||
"serde_json",
|
||||
]
|
||||
|
||||
@@ -2102,6 +2102,25 @@ dependencies = [
|
||||
"litrs",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "download-cef"
|
||||
version = "2.2.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "d98178d9254efef0f69c1f584713d69c790ec00668cd98f783a5085fbefdbddc"
|
||||
dependencies = [
|
||||
"bzip2 0.6.0",
|
||||
"clap",
|
||||
"indicatif",
|
||||
"regex",
|
||||
"semver",
|
||||
"serde",
|
||||
"serde_json",
|
||||
"sha1_smol",
|
||||
"tar",
|
||||
"thiserror 2.0.12",
|
||||
"ureq",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "download-cef"
|
||||
version = "2.2.0"
|
||||
@@ -8758,6 +8777,7 @@ dependencies = [
|
||||
"ctrlc",
|
||||
"dialoguer",
|
||||
"dirs 6.0.0",
|
||||
"download-cef 2.2.0 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"duct",
|
||||
"dunce",
|
||||
"elf",
|
||||
|
||||
@@ -113,6 +113,7 @@ uuid = { version = "1", features = ["v5"] }
|
||||
rand = "0.9"
|
||||
zip = { version = "4", default-features = false, features = ["deflate"] }
|
||||
which = "8"
|
||||
download-cef = "2.2"
|
||||
|
||||
[dev-dependencies]
|
||||
insta = "1"
|
||||
|
||||
@@ -5,5 +5,6 @@
|
||||
},
|
||||
"tauri": "2.9.2",
|
||||
"tauri-build": "2.5.1",
|
||||
"tauri-plugin": "2.5.1"
|
||||
"tauri-plugin": "2.5.1",
|
||||
"cef": "141.6.0+141.0.11"
|
||||
}
|
||||
|
||||
@@ -122,7 +122,7 @@ pub fn command(mut options: Options, verbosity: u8) -> Result<()> {
|
||||
|
||||
let bin_path = interface.build(interface_options)?;
|
||||
|
||||
log::info!(action ="Built"; "application at: {}", tauri_utils::display_path(bin_path));
|
||||
log::info!(action = "Built"; "application at: {}", tauri_utils::display_path(bin_path));
|
||||
|
||||
let app_settings = interface.app_settings();
|
||||
|
||||
|
||||
266
crates/tauri-cli/src/cef/exporter.rs
Normal file
266
crates/tauri-cli/src/cef/exporter.rs
Normal file
@@ -0,0 +1,266 @@
|
||||
// Copyright 2019-2024 Tauri Programme within The Commons Conservancy
|
||||
// SPDX-License-Identifier: Apache-2.0
|
||||
// SPDX-License-Identifier: MIT
|
||||
|
||||
use crate::error::ErrorExt;
|
||||
use crate::VersionMetadata;
|
||||
use download_cef::{CefFile, CefIndex, OsAndArch, DEFAULT_TARGET};
|
||||
use std::{
|
||||
fs,
|
||||
path::{Path, PathBuf},
|
||||
sync::OnceLock,
|
||||
time::Duration,
|
||||
};
|
||||
|
||||
fn default_version() -> &'static str {
|
||||
static DEFAULT_VERSION: OnceLock<String> = OnceLock::new();
|
||||
DEFAULT_VERSION.get_or_init(|| {
|
||||
let metadata: VersionMetadata = serde_json::from_str(include_str!("../../metadata-v2.json"))
|
||||
.expect("failed to parse metadata-v2.json");
|
||||
download_cef::default_version(&metadata.cef)
|
||||
})
|
||||
}
|
||||
|
||||
fn default_download_url() -> &'static str {
|
||||
static DEFAULT_DOWNLOAD_URL: OnceLock<String> = OnceLock::new();
|
||||
DEFAULT_DOWNLOAD_URL
|
||||
.get_or_init(|| download_cef::default_download_url())
|
||||
.as_str()
|
||||
}
|
||||
|
||||
pub struct ExporterOptions {
|
||||
pub output: PathBuf,
|
||||
pub target: String,
|
||||
pub version: Option<String>,
|
||||
pub mirror_url: Option<String>,
|
||||
pub force: bool,
|
||||
pub overwrite: bool,
|
||||
pub archive: Option<PathBuf>,
|
||||
}
|
||||
|
||||
impl Default for ExporterOptions {
|
||||
fn default() -> Self {
|
||||
Self {
|
||||
output: PathBuf::new(),
|
||||
target: DEFAULT_TARGET.to_string(),
|
||||
version: None,
|
||||
mirror_url: None,
|
||||
force: false,
|
||||
overwrite: false,
|
||||
archive: None,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
pub fn export_cef_directory(options: ExporterOptions) -> crate::Result<()> {
|
||||
let output = &options.output;
|
||||
let url = options
|
||||
.mirror_url
|
||||
.unwrap_or_else(|| default_download_url().to_string());
|
||||
let version = options
|
||||
.version
|
||||
.unwrap_or_else(|| default_version().to_string());
|
||||
|
||||
let parent = output.parent().ok_or_else(|| {
|
||||
crate::Error::GenericError(format!("invalid target directory: {}", output.display()))
|
||||
})?;
|
||||
|
||||
// Check if directory exists and has valid archive.json
|
||||
let archive_json_path = output.join("archive.json");
|
||||
let needs_update = if output.exists() && archive_json_path.exists() {
|
||||
if options.force {
|
||||
true
|
||||
} else {
|
||||
// Check if archive.json indicates we need an update
|
||||
match check_archive_outdated(&archive_json_path, &version) {
|
||||
Ok(true) => {
|
||||
log::info!(action = "CEF"; "CEF directory is outdated, will update");
|
||||
true
|
||||
}
|
||||
Ok(false) => false,
|
||||
Err(e) => {
|
||||
log::warn!(action = "CEF"; "Failed to check archive.json: {e}. Will update.");
|
||||
true
|
||||
}
|
||||
}
|
||||
}
|
||||
} else {
|
||||
true
|
||||
};
|
||||
|
||||
if !needs_update {
|
||||
return Ok(());
|
||||
}
|
||||
|
||||
if output.exists() {
|
||||
if !options.overwrite {
|
||||
return Err(crate::Error::GenericError(format!(
|
||||
"target directory already exists: {}. Use overwrite=true to overwrite it.",
|
||||
output.display()
|
||||
)));
|
||||
}
|
||||
|
||||
let dir = output
|
||||
.file_name()
|
||||
.and_then(|dir| dir.to_str())
|
||||
.ok_or_else(|| {
|
||||
crate::Error::GenericError(format!("invalid target directory: {}", output.display()))
|
||||
})?;
|
||||
let old_output = parent.join(format!("old_{dir}"));
|
||||
if old_output.exists() {
|
||||
fs::remove_dir_all(&old_output)
|
||||
.fs_context("failed to remove old output directory", old_output.clone())?;
|
||||
}
|
||||
fs::rename(output, &old_output)
|
||||
.fs_context("failed to rename output directory", old_output.clone())?;
|
||||
log::info!(action = "CEF"; "Cleaning up: {}", old_output.display());
|
||||
fs::remove_dir_all(&old_output)
|
||||
.fs_context("failed to remove old output directory", old_output)?;
|
||||
}
|
||||
|
||||
let target_str = options.target.as_str();
|
||||
let os_arch = OsAndArch::try_from(target_str)
|
||||
.map_err(|e| crate::Error::GenericError(format!("invalid target: {e}")))?;
|
||||
let cef_dir = os_arch.to_string();
|
||||
let cef_dir = parent.join(&cef_dir);
|
||||
|
||||
if cef_dir.exists() {
|
||||
let dir = cef_dir
|
||||
.file_name()
|
||||
.and_then(|dir| dir.to_str())
|
||||
.ok_or_else(|| {
|
||||
crate::Error::GenericError(format!("invalid target directory: {}", output.display()))
|
||||
})?;
|
||||
let old_cef_dir = parent.join(format!("old_{dir}"));
|
||||
if old_cef_dir.exists() {
|
||||
fs::remove_dir_all(&old_cef_dir)
|
||||
.fs_context("failed to remove old cef directory", old_cef_dir.clone())?;
|
||||
}
|
||||
fs::rename(&cef_dir, &old_cef_dir)
|
||||
.fs_context("failed to rename cef directory", old_cef_dir.clone())?;
|
||||
log::info!(action = "CEF"; "Cleaning up: {}", old_cef_dir.display());
|
||||
fs::remove_dir_all(&old_cef_dir)
|
||||
.fs_context("failed to remove old cef directory", old_cef_dir)?;
|
||||
}
|
||||
|
||||
let (archive, extracted_dir) = match options.archive {
|
||||
Some(archive) => {
|
||||
let extracted_dir = download_cef::extract_target_archive(target_str, &archive, parent, true)
|
||||
.map_err(|e| crate::Error::GenericError(format!("failed to extract archive: {e}")))?;
|
||||
let archive = CefFile::try_from(archive.as_path())
|
||||
.map_err(|e| crate::Error::GenericError(format!("invalid archive file: {e}")))?;
|
||||
(archive, extracted_dir)
|
||||
}
|
||||
None => {
|
||||
log::info!(action = "CEF"; "Downloading CEF version {version} for target {target_str}");
|
||||
let index = CefIndex::download_from(&url)
|
||||
.map_err(|e| crate::Error::GenericError(format!("failed to download CEF index: {e}")))?;
|
||||
let platform = index.platform(target_str).map_err(|e| {
|
||||
crate::Error::GenericError(format!("platform not found for target {target_str}: {e}"))
|
||||
})?;
|
||||
let version = platform
|
||||
.version(&version)
|
||||
.map_err(|e| crate::Error::GenericError(format!("version {version} not found: {e}")))?;
|
||||
|
||||
let archive = version
|
||||
.download_archive_with_retry_from(&url, parent, true, Duration::from_secs(15), 3)
|
||||
.map_err(|e| crate::Error::GenericError(format!("failed to download CEF archive: {e}")))?;
|
||||
let extracted_dir = download_cef::extract_target_archive(target_str, &archive, parent, true)
|
||||
.map_err(|e| crate::Error::GenericError(format!("failed to extract archive: {e}")))?;
|
||||
|
||||
fs::remove_file(&archive).fs_context("failed to remove archive", archive.clone())?;
|
||||
|
||||
let archive = version
|
||||
.minimal()
|
||||
.map_err(|e| {
|
||||
crate::Error::GenericError(format!("failed to get minimal archive info: {e}"))
|
||||
})?
|
||||
.clone();
|
||||
(archive, extracted_dir)
|
||||
}
|
||||
};
|
||||
|
||||
if extracted_dir != cef_dir {
|
||||
return Err(crate::Error::GenericError(format!(
|
||||
"extracted dir {extracted_dir:?} does not match cef_dir {cef_dir:?}",
|
||||
)));
|
||||
}
|
||||
|
||||
archive
|
||||
.write_archive_json(extracted_dir.as_path())
|
||||
.map_err(|e| crate::Error::GenericError(format!("failed to write archive.json: {e}")))?;
|
||||
|
||||
if output != &cef_dir {
|
||||
log::info!(action = "CEF"; "Renaming: {}", output.display());
|
||||
fs::rename(&cef_dir, output)
|
||||
.fs_context("failed to rename cef directory to output", output.clone())?;
|
||||
}
|
||||
|
||||
// Set CEF_PATH environment variable
|
||||
std::env::set_var("CEF_PATH", output.to_string_lossy().as_ref());
|
||||
log::info!(action = "CEF"; "CEF directory exported to: {}", output.display());
|
||||
|
||||
Ok(())
|
||||
}
|
||||
|
||||
fn check_archive_outdated(archive_json_path: &Path, required_version: &str) -> crate::Result<bool> {
|
||||
let content = fs::read_to_string(archive_json_path).fs_context(
|
||||
"failed to read archive.json",
|
||||
archive_json_path.to_path_buf(),
|
||||
)?;
|
||||
let archive_info: serde_json::Value = serde_json::from_str(&content)
|
||||
.map_err(|e| crate::Error::GenericError(format!("failed to parse archive.json: {e}")))?;
|
||||
|
||||
if let Some(name) = archive_info.get("name").and_then(|v| v.as_str()) {
|
||||
Ok(!name.contains(required_version))
|
||||
} else {
|
||||
Ok(true)
|
||||
}
|
||||
}
|
||||
|
||||
pub fn ensure_cef_directory(
|
||||
target: Option<&str>,
|
||||
enabled_features: &[String],
|
||||
) -> crate::Result<Option<PathBuf>> {
|
||||
// Check if cef feature is enabled
|
||||
let cef_enabled = enabled_features
|
||||
.iter()
|
||||
.any(|f| f == "cef" || f == "tauri/cef");
|
||||
|
||||
if !cef_enabled {
|
||||
return Ok(None);
|
||||
}
|
||||
|
||||
let target = target.unwrap_or(DEFAULT_TARGET);
|
||||
let os_arch = OsAndArch::try_from(target)
|
||||
.map_err(|e| crate::Error::GenericError(format!("invalid target: {e}")))?;
|
||||
|
||||
let cef_dir = if let Ok(cef_path) = std::env::var("CEF_PATH") {
|
||||
let path = PathBuf::from(cef_path);
|
||||
// If CEF_PATH is set but directory doesn't exist, we'll create it
|
||||
if !path.exists() {
|
||||
log::info!(action = "CEF"; "CEF_PATH set but directory doesn't exist, will export to {}", path.display());
|
||||
}
|
||||
path
|
||||
} else {
|
||||
// Default to a directory in the user's cache or home directory
|
||||
let base_dir = dirs::cache_dir()
|
||||
.or_else(dirs::home_dir)
|
||||
.ok_or_else(|| crate::Error::GenericError("failed to find cache or home directory".into()))?;
|
||||
base_dir.join("tauri-cef").join(os_arch.to_string())
|
||||
};
|
||||
|
||||
export_cef_directory(ExporterOptions {
|
||||
output: cef_dir.clone(),
|
||||
target: target.to_string(),
|
||||
version: None,
|
||||
mirror_url: None,
|
||||
force: false,
|
||||
overwrite: true,
|
||||
archive: None,
|
||||
})?;
|
||||
|
||||
std::env::set_var("CEF_PATH", cef_dir.to_string_lossy().as_ref());
|
||||
|
||||
Ok(Some(cef_dir))
|
||||
}
|
||||
@@ -1,11 +1,8 @@
|
||||
// Copyright 2019-2024 Tauri Programme within The Commons Conservancy
|
||||
// SPDX-License-Identifier: Apache-2.0
|
||||
// SPDX-License-Identifier: MIT
|
||||
|
||||
#![cfg(target_os = "macos")]
|
||||
|
||||
use super::{desktop::DevChild, ExitReason, Options, RustAppSettings, RustupTarget};
|
||||
use crate::{error::ErrorExt, interface::AppSettings, CommandExt};
|
||||
use crate::interface::rust::desktop::DevChild;
|
||||
use crate::interface::{AppSettings, ExitReason, Options, RustAppSettings, RustupTarget};
|
||||
use crate::{error::ErrorExt, CommandExt};
|
||||
|
||||
use serde::Serialize;
|
||||
use shared_child::SharedChild;
|
||||
@@ -112,8 +109,8 @@ fn copy_dir_all(src: &Path, dst: &Path) -> crate::Result<()> {
|
||||
Ok(())
|
||||
}
|
||||
|
||||
pub fn run_dev_cef_macos<F: Fn(Option<i32>, ExitReason) + Send + Sync + 'static>(
|
||||
app_settings: &RustAppSettings,
|
||||
pub fn run_dev_cef_macos<A: AppSettings, F: Fn(Option<i32>, ExitReason) + Send + Sync + 'static>(
|
||||
app_settings: &A,
|
||||
options: Options,
|
||||
run_args: Vec<String>,
|
||||
available_targets: &mut Option<Vec<RustupTarget>>,
|
||||
@@ -121,8 +118,12 @@ pub fn run_dev_cef_macos<F: Fn(Option<i32>, ExitReason) + Send + Sync + 'static>
|
||||
on_exit: F,
|
||||
) -> crate::Result<DevChild> {
|
||||
// Build the app
|
||||
let mut build_cmd =
|
||||
super::desktop::cargo_command(false, options.clone(), available_targets, config_features)?;
|
||||
let mut build_cmd = crate::interface::rust::desktop::cargo_command(
|
||||
false,
|
||||
options.clone(),
|
||||
available_targets,
|
||||
config_features,
|
||||
)?;
|
||||
build_cmd.env("CARGO_TERM_PROGRESS_WIDTH", "80");
|
||||
build_cmd.env("CARGO_TERM_PROGRESS_WHEN", "always");
|
||||
match build_cmd.piped() {
|
||||
8
crates/tauri-cli/src/cef/mod.rs
Normal file
8
crates/tauri-cli/src/cef/mod.rs
Normal file
@@ -0,0 +1,8 @@
|
||||
// Copyright 2019-2024 Tauri Programme within The Commons Conservancy
|
||||
// SPDX-License-Identifier: Apache-2.0
|
||||
// SPDX-License-Identifier: MIT
|
||||
|
||||
#[cfg(target_os = "macos")]
|
||||
pub mod macos_dev;
|
||||
|
||||
pub mod exporter;
|
||||
@@ -39,8 +39,6 @@ use crate::{
|
||||
use tauri_utils::{display_path, platform::Target as TargetPlatform};
|
||||
|
||||
mod cargo_config;
|
||||
#[cfg(target_os = "macos")]
|
||||
mod cef;
|
||||
mod desktop;
|
||||
pub mod installation;
|
||||
pub mod manifest;
|
||||
@@ -189,6 +187,12 @@ impl Interface for Rust {
|
||||
}
|
||||
|
||||
fn build(&mut self, options: Options) -> crate::Result<PathBuf> {
|
||||
ensure_cef_directory_if_needed(
|
||||
&self.app_settings,
|
||||
self.config_features.clone(),
|
||||
options.target.as_deref(),
|
||||
&options.features,
|
||||
)?;
|
||||
desktop::build(
|
||||
options,
|
||||
&self.app_settings,
|
||||
@@ -203,6 +207,12 @@ impl Interface for Rust {
|
||||
mut options: Options,
|
||||
on_exit: F,
|
||||
) -> crate::Result<()> {
|
||||
ensure_cef_directory_if_needed(
|
||||
&self.app_settings,
|
||||
self.config_features.clone(),
|
||||
options.target.as_deref(),
|
||||
&options.features,
|
||||
)?;
|
||||
let on_exit = Arc::new(on_exit);
|
||||
|
||||
let mut run_args = Vec::new();
|
||||
@@ -499,6 +509,34 @@ fn get_watch_folders(additional_watch_folders: &[PathBuf]) -> crate::Result<Vec<
|
||||
Ok(watch_folders)
|
||||
}
|
||||
|
||||
fn ensure_cef_directory_if_needed(
|
||||
app_settings: &RustAppSettings,
|
||||
config_features: Vec<String>,
|
||||
target: Option<&str>,
|
||||
features: &Option<Vec<String>>,
|
||||
) -> crate::Result<()> {
|
||||
let mut merged_features = config_features;
|
||||
if let Some(f) = features {
|
||||
merged_features.extend(f.clone());
|
||||
}
|
||||
let enabled_features = app_settings
|
||||
.manifest
|
||||
.lock()
|
||||
.unwrap()
|
||||
.all_enabled_features(&merged_features);
|
||||
let target_triple = target.or_else(|| {
|
||||
app_settings
|
||||
.cargo_config
|
||||
.build()
|
||||
.target()
|
||||
.map(|t| t.as_ref())
|
||||
});
|
||||
if let Err(e) = crate::cef::exporter::ensure_cef_directory(target_triple, &enabled_features) {
|
||||
log::warn!(action = "CEF"; "Failed to ensure CEF directory: {}. Continuing anyway.", e);
|
||||
}
|
||||
Ok(())
|
||||
}
|
||||
|
||||
impl Rust {
|
||||
pub fn build_options(
|
||||
&self,
|
||||
|
||||
@@ -71,7 +71,7 @@ pub fn run_dev<F: Fn(Option<i32>, ExitReason) + Send + Sync + 'static>(
|
||||
let cef_enabled = enabled_features.contains(&"cef".to_string())
|
||||
|| enabled_features.contains(&"tauri/cef".to_string());
|
||||
if cef_enabled {
|
||||
return super::cef::run_dev_cef_macos(
|
||||
return crate::cef::macos_dev::run_dev_cef_macos(
|
||||
app_settings,
|
||||
options,
|
||||
run_args,
|
||||
|
||||
@@ -14,6 +14,7 @@ mod acl;
|
||||
mod add;
|
||||
mod build;
|
||||
mod bundle;
|
||||
mod cef;
|
||||
mod completions;
|
||||
mod dev;
|
||||
mod error;
|
||||
@@ -122,6 +123,8 @@ pub struct VersionMetadata {
|
||||
tauri_build: String,
|
||||
#[serde(rename = "tauri-plugin")]
|
||||
tauri_plugin: String,
|
||||
#[serde(rename = "cef")]
|
||||
cef: String,
|
||||
}
|
||||
|
||||
#[derive(Deserialize)]
|
||||
|
||||
@@ -1295,7 +1295,7 @@ impl<R: Runtime> App<R> {
|
||||
let app_handle = self.handle().clone();
|
||||
let manager = self.manager.clone();
|
||||
|
||||
move |event| match dbg!(&event) {
|
||||
move |event| match &event {
|
||||
RuntimeRunEvent::Ready => {
|
||||
if let Err(e) = setup(&mut self) {
|
||||
panic!("Failed to setup app: {e}");
|
||||
|
||||
Reference in New Issue
Block a user