2026-03-03 23:16:04 +11:00
|
|
|
#![cfg_attr(
|
|
|
|
|
all(not(debug_assertions), target_os = "windows"),
|
|
|
|
|
windows_subsystem = "windows"
|
|
|
|
|
)]
|
|
|
|
|
|
2026-04-13 15:20:44 +08:00
|
|
|
use tauri::{webview::{NewWindowResponse, WebviewWindowBuilder}, WebviewUrl};
|
|
|
|
|
use tauri_plugin_opener::OpenerExt;
|
2026-03-03 23:16:04 +11:00
|
|
|
|
|
|
|
|
pub fn run() {
|
|
|
|
|
let port: u16 = 44548;
|
|
|
|
|
let context = tauri::generate_context!();
|
|
|
|
|
let builder = tauri::Builder::default();
|
|
|
|
|
|
|
|
|
|
builder
|
|
|
|
|
.plugin(tauri_plugin_localhost::Builder::new(port).build())
|
|
|
|
|
.plugin(tauri_plugin_window_state::Builder::default().build())
|
2026-04-13 15:20:44 +08:00
|
|
|
.plugin(tauri_plugin_opener::init())
|
2026-03-03 23:16:04 +11:00
|
|
|
.setup(move |app| {
|
2026-03-17 21:29:22 +08:00
|
|
|
#[cfg(debug_assertions)]
|
|
|
|
|
let window_url = WebviewUrl::App(Default::default());
|
|
|
|
|
|
|
|
|
|
#[cfg(not(debug_assertions))]
|
|
|
|
|
let window_url = {
|
|
|
|
|
let url = format!("http://localhost:{}", port).parse().unwrap();
|
|
|
|
|
WebviewUrl::External(url)
|
|
|
|
|
};
|
|
|
|
|
|
2026-04-13 15:20:44 +08:00
|
|
|
let app_handle = app.handle().clone();
|
2026-06-10 10:05:49 -04:00
|
|
|
let window = WebviewWindowBuilder::new(app, "main".to_string(), window_url)
|
2026-03-03 23:16:04 +11:00
|
|
|
.title("Cinny")
|
2026-05-23 21:52:14 +10:00
|
|
|
.disable_drag_drop_handler()
|
2026-04-13 15:20:44 +08:00
|
|
|
.on_new_window(move |url, _features| {
|
|
|
|
|
let _ = app_handle.opener().open_url(url.as_str(), None::<&str>);
|
|
|
|
|
NewWindowResponse::Deny
|
2026-06-10 10:05:49 -04:00
|
|
|
})
|
|
|
|
|
.build()?;
|
2026-06-09 18:27:12 -04:00
|
|
|
|
2026-06-09 23:31:03 -04:00
|
|
|
// Grant camera and microphone to WebView2 automatically.
|
2026-06-10 10:05:49 -04:00
|
|
|
// Windows requires an explicit PermissionRequested COM event handler.
|
2026-06-09 21:51:56 -04:00
|
|
|
#[cfg(target_os = "windows")]
|
2026-06-10 10:05:49 -04:00
|
|
|
window.with_webview(|webview| {
|
2026-06-09 23:31:03 -04:00
|
|
|
use webview2_com::{
|
|
|
|
|
Microsoft::Web::WebView2::Win32::{
|
2026-06-10 10:05:49 -04:00
|
|
|
COREWEBVIEW2_PERMISSION_KIND,
|
2026-06-09 23:31:03 -04:00
|
|
|
COREWEBVIEW2_PERMISSION_KIND_CAMERA,
|
|
|
|
|
COREWEBVIEW2_PERMISSION_KIND_MICROPHONE,
|
|
|
|
|
COREWEBVIEW2_PERMISSION_STATE_ALLOW,
|
|
|
|
|
},
|
|
|
|
|
PermissionRequestedEventHandler,
|
|
|
|
|
};
|
2026-06-09 21:51:56 -04:00
|
|
|
|
|
|
|
|
let controller = webview.controller();
|
|
|
|
|
if let Ok(core) = unsafe { controller.CoreWebView2() } {
|
2026-06-09 23:31:03 -04:00
|
|
|
let handler = PermissionRequestedEventHandler::create(Box::new(
|
|
|
|
|
|_sender, args| {
|
|
|
|
|
if let Some(args) = args {
|
2026-06-10 00:06:12 -04:00
|
|
|
let mut kind = COREWEBVIEW2_PERMISSION_KIND(0);
|
|
|
|
|
unsafe { args.PermissionKind(&mut kind) }?;
|
2026-06-09 23:31:03 -04:00
|
|
|
if kind == COREWEBVIEW2_PERMISSION_KIND_MICROPHONE
|
|
|
|
|
|| kind == COREWEBVIEW2_PERMISSION_KIND_CAMERA
|
|
|
|
|
{
|
|
|
|
|
unsafe {
|
|
|
|
|
args.SetState(COREWEBVIEW2_PERMISSION_STATE_ALLOW)
|
|
|
|
|
}?;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
Ok(())
|
|
|
|
|
},
|
|
|
|
|
));
|
|
|
|
|
let mut token = Default::default();
|
2026-06-09 21:51:56 -04:00
|
|
|
let _ = unsafe { core.add_PermissionRequested(&handler, &mut token) };
|
|
|
|
|
}
|
2026-06-10 10:05:49 -04:00
|
|
|
})?;
|
2026-06-09 21:51:56 -04:00
|
|
|
|
2026-03-03 23:16:04 +11:00
|
|
|
Ok(())
|
|
|
|
|
})
|
|
|
|
|
.run(context)
|
|
|
|
|
.expect("error while building tauri application");
|
|
|
|
|
}
|