Skip to main content

webui/
lib.rs

1#![warn(missing_docs)]
2
3//! Rust bindings to WebUI.
4
5mod context;
6mod error;
7mod event;
8mod handler;
9mod types;
10mod window;
11
12pub(crate) use context::*;
13pub use error::*;
14pub use event::*;
15pub use types::*;
16pub use window::*;
17
18use std::{
19    ffi::{c_char, c_void, CStr, CString},
20    panic::{catch_unwind, AssertUnwindSafe},
21};
22
23use webui_sys::*;
24
25use crate::handler::LoggerHandler;
26
27/// Close all open windows. This will make wait() return (Break).
28pub fn exit() {
29    unsafe { webui_exit() }
30}
31
32/// Block the current thread and wait until all opened windows get closed.
33pub fn wait() {
34    unsafe { webui_wait() }
35}
36
37/// Non-blocking alternative to wait(). Returns true if at least one window is still open, false when all windows are
38/// closed. Call this in a loop from the main thread to interleave your own main-thread work.
39///
40/// # Safety
41/// In WebView mode, you must call this from the main thread.
42pub fn wait_async() -> bool {
43    unsafe { webui_wait_async() }
44}
45
46/// Open a URL in the operating system's default web browser (not a WebUI window).
47pub fn open_url(url: &str) {
48    let url = CString::new(url).unwrap();
49    unsafe { webui_open_url(url.as_ptr()) }
50}
51
52/// Control WebUI global behaviour. It's recommended to call this at the beginning, before show().
53pub(crate) fn set_config(option: Config, status: bool) {
54    unsafe {
55        webui_set_config(option as _, status);
56    }
57}
58
59/// Wait for browser to connect before show() returns.
60/// Default: true
61pub fn set_show_wait_connection(status: bool) {
62    set_config(Config::ShowWaitConnection, status);
63}
64
65/// Process all UI events in a single blocking thread (true)
66/// or each in a new thread (false). Applies to all windows.
67/// Default: false
68pub fn set_ui_event_blocking(status: bool) {
69    set_config(Config::UiEventBlocking, status);
70}
71
72/// Auto-refresh the window when any file in the root folder changes.
73/// Default: false
74pub fn set_folder_monitor(status: bool) {
75    set_config(Config::FolderMonitor, status);
76}
77
78/// Allow multiple browser clients to connect to the same window.
79/// Useful for web apps. See documentation for details.
80/// Default: false
81pub fn set_multi_client(status: bool) {
82    set_config(Config::MultiClient, status);
83}
84
85/// Use WebUI auth cookies to identify clients and block unauthorized
86/// URL access. Keep true to restrict access to one client at a time.
87/// Default: true
88pub fn set_use_cookies(status: bool) {
89    set_config(Config::UseCookies, status);
90}
91
92/// Set to true if your backend uses async operations and sets
93/// responses via webui_return_x() after the callback returns.
94/// Default: false
95pub fn set_asynchronous_response(status: bool) {
96    set_config(Config::AsynchronousResponse, status);
97}
98
99/// Set the web-server root folder path for all windows.
100pub fn set_default_root_folder(path: &str) -> Result<(), WebUIError> {
101    let path = CString::new(path).unwrap();
102    let result = unsafe { webui_set_default_root_folder(path.as_ptr()) };
103    WebUIError::from_bool(result)
104}
105
106/// Get the HTTP MIME type string for a given file extension.
107pub fn get_mime_type(file: &str) -> String {
108    let file = CString::new(file).unwrap();
109    unsafe {
110        let mine_type = webui_get_mime_type(file.as_ptr());
111        CStr::from_ptr(mine_type).to_string_lossy().to_string()
112    }
113}
114
115/// Check whether a specific web browser is installed on the system.
116pub fn browser_exist(browser: Browser) -> bool {
117    unsafe { webui_browser_exist(browser as _) }
118}
119
120/// Set a custom folder path where WebUI should look for the browser executable.
121pub fn set_browser_folder(path: &str) {
122    let path = CString::new(path).unwrap();
123    unsafe { webui_set_browser_folder(path.as_ptr()) }
124}
125
126/// Delete all local web-browser profile folders created by WebUI.
127pub fn delete_all_profiles() {
128    unsafe { webui_delete_all_profiles() }
129}
130
131/// Find and return an available (unused) network port.
132pub fn get_port() -> usize {
133    unsafe { webui_get_free_port() }
134}
135
136/// Encode a string to Base64.
137pub fn encode(text: &str) -> String {
138    let text = CString::new(text).unwrap();
139    let encoded = unsafe { webui_encode(text.as_ptr()) };
140    let result = unsafe { CStr::from_ptr(encoded as _).to_string_lossy().to_string() };
141    unsafe { webui_free(encoded as _) };
142    result
143}
144
145/// Decode a Base64-encoded string.
146pub fn decode(text: &str) -> String {
147    let text = CString::new(text).unwrap();
148    let decoded = unsafe { webui_decode(text.as_ptr()) };
149    let result = unsafe { CStr::from_ptr(decoded as _).to_string_lossy().to_string() };
150    unsafe { webui_free(decoded as _) };
151    result
152}
153
154/// Set the SSL/TLS certificate and private key (both in PEM format). If called with empty strings, WebUI generates
155/// a self-signed certificate.
156///
157/// # Remarks
158/// This works only with the TLS build of WebUI (webui-2-secure).
159pub fn set_tls_certificate(certificate_pem: &str, private_key_pem: &str) -> Result<(), WebUIError> {
160    let certificate_pem = CString::new(certificate_pem).unwrap();
161    let private_key_pem = CString::new(private_key_pem).unwrap();
162    let result = unsafe { webui_set_tls_certificate(certificate_pem.as_ptr(), private_key_pem.as_ptr()) };
163    WebUIError::from_bool(result)
164}
165
166/// Set a custom logging function to receive WebUI's internal log messages. Useful for debugging or integrating with your
167/// own logging system.
168pub fn set_logger<F>(callback: F)
169where
170    F: LoggerHandler,
171{
172    extern "C" fn shim(level: usize, log: *const c_char, user_data: *mut c_void) {
173        let level: LoggerLevel = unsafe { std::mem::transmute(level) };
174        let log = unsafe { CStr::from_ptr(log).to_string_lossy().to_string() };
175        let callback = unsafe { &*(user_data as *mut Box<dyn LoggerHandler>) };
176        let _ = catch_unwind(AssertUnwindSafe(|| callback(level, &log)));
177    }
178    let user_data: Box<dyn LoggerHandler> = Box::new(callback);
179    let user_data = Box::into_raw(Box::new(user_data));
180    unsafe {
181        webui_set_logger(Some(shim), user_data as _);
182    }
183}
184
185/// Free all memory resources used by WebUI. Should be called only once at the very end of your application,
186/// after wait() returns.
187pub unsafe fn clean() {
188    webui_clean();
189}
190
191/// Get the error code from the most recent WebUI operation that failed.
192pub(crate) fn get_last_error_number() -> usize {
193    unsafe { webui_get_last_error_number() }
194}
195
196/// Get the human-readable error message from the most recent WebUI operation that failed.
197pub(crate) fn get_last_error_message() -> String {
198    unsafe {
199        let message = webui_get_last_error_message();
200        CStr::from_ptr(message).to_string_lossy().to_string()
201    }
202}