#![deny(missing_docs)]
#[cfg(doctest)]
#[doc = include_str!("../README.md")]
pub struct ReadmeDoctests;
#[cfg(desktop)]
mod a11y;
#[cfg(web)]
mod a11y_web;
#[cfg(web)]
mod address;
#[cfg(android)]
mod android_autofill;
#[cfg(android)]
mod android_clipboard;
#[cfg(android)]
mod android_ime;
#[cfg(android)]
mod android_link;
#[cfg(all(android, feature = "notifications"))]
mod android_notification;
#[cfg(android)]
mod android_settings;
#[cfg(android)]
mod android_system_bars;
mod app;
mod application;
#[cfg(any(android, test))]
mod autofill;
mod cache_dir;
mod caret;
mod command;
#[cfg(all(desktop, feature = "file-dialogs"))]
mod file_dialog;
mod file_drop;
mod frame_stats;
mod gesture;
#[cfg(any(web, test))]
mod history;
mod hover;
mod icon;
#[cfg(any(android, test))]
mod ime;
#[cfg(desktop)]
mod instance;
#[cfg(any(
all(desktop, feature = "file-dialogs"),
all(any(desktop, android), feature = "notifications")
))]
mod interface_thread;
mod link;
mod logging;
#[cfg(feature = "net")]
pub mod net;
#[cfg(all(any(desktop, android, web), feature = "notifications"))]
mod notification;
#[cfg(all(web, feature = "notifications"))]
mod notification_web;
mod reload;
mod shortcuts;
mod startup;
mod taskbar;
mod tray;
#[cfg(web)]
mod web_dev;
#[cfg(feature = "hot-reload")]
mod hot;
#[cfg(any(desktop, android))]
mod dev;
mod dev_commands;
mod remote;
#[cfg(not(web))]
pub(crate) mod runtime;
mod selection;
mod simulated;
mod subscription;
mod theming;
#[cfg(windows)]
mod title_bar;
#[cfg(web)]
mod web_clipboard;
#[cfg(any(web, test))]
mod web_editing;
#[cfg(web)]
mod web_icon;
#[cfg(any(web, test))]
mod web_keys;
mod widget_app;
#[cfg(any(test, feature = "testing"))]
#[doc(hidden)]
pub use app::testing;
pub use app::App;
pub use application::{Application, Lifecycle, LocationStrategy};
pub use command::Command;
#[cfg(all(desktop, feature = "file-dialogs"))]
pub use file_dialog::FileDialog;
pub use icon::AppIcon;
pub use link::{link_among, location_of_link};
#[cfg(all(any(desktop, android, web), feature = "notifications"))]
pub use notification::{NotificationError, NotificationResponse, SystemNotification};
pub use remote::RemoteData;
pub use shortcuts::GlobalShortcut;
pub use subscription::Subscription;
pub use taskbar::{Taskbar, TaskbarProgress};
pub use tray::Tray;
pub use widget_app::FrusApp;
#[cfg(feature = "net")]
pub use net::{fetch, fetch_bytes, FetchError, Method, Request, MAX_RESPONSE_BYTES};
pub use frus_widgets::{Brightness, Locale, Orientation, ScrollPhysics, SizeClass, ThemeMode};
#[cfg(android)]
pub use winit::platform::android::activity::AndroidApp;
#[doc(hidden)]
pub use anyhow;
#[doc(hidden)]
pub use log;
#[doc(hidden)]
pub use logging::name_app as __name_app;
#[doc(hidden)]
#[macro_export]
#[cfg(all(
feature = "hot-reload",
not(any(target_os = "android", target_arch = "wasm32"))
))]
macro_rules! __hot_main {
() => {
#[allow(dead_code)]
fn main() -> $crate::anyhow::Result<()> {
run()
}
};
}
#[doc(hidden)]
#[macro_export]
#[cfg(all(
feature = "hot-reload",
any(target_arch = "wasm32", target_os = "android")
))]
macro_rules! __hot_main {
() => {
#[allow(dead_code)]
fn main() {}
};
}
#[doc(hidden)]
#[macro_export]
#[cfg(not(feature = "hot-reload"))]
macro_rules! __hot_main {
() => {};
}
#[macro_export]
macro_rules! main {
($app:expr $(,)?) => {
#[cfg(not(any(target_os = "android", target_arch = "wasm32")))]
pub fn run() -> $crate::anyhow::Result<()> {
$crate::__name_app(::core::module_path!());
$crate::run($app)
}
$crate::__hot_main!();
#[cfg(target_os = "android")]
#[no_mangle]
fn android_main(android_app: $crate::AndroidApp) {
$crate::__name_app(::core::module_path!());
if let ::core::result::Result::Err(err) = $crate::run_android($app, android_app) {
$crate::log::error!("frus (android) stopped: {:#}", err);
}
}
#[cfg(target_arch = "wasm32")]
#[::wasm_bindgen::prelude::wasm_bindgen(start)]
pub fn start() {
$crate::__name_app(::core::module_path!());
if let ::core::result::Result::Err(err) = $crate::run_web($app) {
$crate::log::error!("frus (web) stopped: {:#}", err);
}
}
};
}
#[cfg(desktop)]
pub fn run<A: Application>(mut app: A) -> anyhow::Result<()> {
startup::begin();
if let Some(dir) = std::env::current_exe().ok().and_then(|exe| {
cache_dir::desktop(
std::env::consts::OS,
|name| std::env::var_os(name),
exe.file_stem()?,
)
}) {
frus_gpu::set_pipeline_cache_dir(dir);
}
logging::init::<A>();
reload::restore_from_env(&mut app);
if let Some(id) = app.instance_id() {
match instance::claim(&id, link::link_among(std::env::args()).as_deref()) {
instance::Claim::Handed => return Ok(()),
instance::Claim::First(server) => instance::serve_into_queue(server),
}
}
let event_loop = winit::event_loop::EventLoop::<A::Message>::with_user_event().build()?;
event_loop.set_control_flow(winit::event_loop::ControlFlow::Wait);
let proxy = event_loop.create_proxy();
let mut app = App::new(app, proxy);
event_loop.run_app(&mut app)?;
Ok(())
}
#[cfg(ios)]
pub fn run<A: Application>(app: A) -> anyhow::Result<()> {
startup::begin();
let event_loop = winit::event_loop::EventLoop::<A::Message>::with_user_event().build()?;
event_loop.set_control_flow(winit::event_loop::ControlFlow::Wait);
let proxy = event_loop.create_proxy();
let mut app = App::new(app, proxy);
event_loop.run_app(&mut app)?;
Ok(())
}
#[cfg(web)]
pub fn run_web<A: Application + 'static>(app: A) -> anyhow::Result<()> {
use winit::platform::web::EventLoopExtWebSys;
startup::begin();
console_error_panic_hook::set_once();
logging::init::<A>();
if let Some(navigator) = web_sys::window().map(|window| window.navigator()) {
let platform = frus_widgets::TargetPlatform::from_browser(
&navigator.platform().unwrap_or_default(),
&navigator.user_agent().unwrap_or_default(),
navigator.max_touch_points(),
);
frus_widgets::__set_detected_target_platform(platform);
log::info!("target platform: {platform}, from the browser");
}
let event_loop = winit::event_loop::EventLoop::<A::Message>::with_user_event().build()?;
event_loop.set_control_flow(winit::event_loop::ControlFlow::Wait);
let proxy = event_loop.create_proxy();
let app = App::new(app, proxy);
event_loop.spawn_app(app);
Ok(())
}
#[cfg(android)]
pub fn run_android<A: Application>(app: A, android_app: AndroidApp) -> anyhow::Result<()> {
use winit::platform::android::EventLoopBuilderExtAndroid;
startup::begin();
if let Some(files) = android_app.internal_data_path() {
let (now, before) = (
cache_dir::android(&files),
cache_dir::android_before_697(&files),
);
if before != now {
let _ = std::fs::remove_dir_all(before);
}
frus_gpu::set_pipeline_cache_dir(now);
}
logging::init::<A>();
let event_loop = winit::event_loop::EventLoop::<A::Message>::with_user_event()
.with_android_app(android_app.clone())
.build()?;
event_loop.set_control_flow(winit::event_loop::ControlFlow::Wait);
let proxy = event_loop.create_proxy();
let mut app = App::new(app, proxy);
android_ime::install(&android_app);
app.set_android_app(android_app);
event_loop.run_app(&mut app)?;
std::process::exit(0);
}