141 lines
4.0 KiB
Rust
141 lines
4.0 KiB
Rust
use crate::constants::{UPDATER_ENABLED, window_state_flags};
|
|
use std::{ops::Deref, time::Duration};
|
|
use tauri::{AppHandle, Manager, Runtime, WebviewUrl, WebviewWindow, WebviewWindowBuilder};
|
|
use tauri_plugin_window_state::AppHandleExt;
|
|
use tokio::sync::mpsc;
|
|
|
|
pub struct MainWindow(WebviewWindow);
|
|
|
|
impl Deref for MainWindow {
|
|
type Target = WebviewWindow;
|
|
|
|
fn deref(&self) -> &Self::Target {
|
|
&self.0
|
|
}
|
|
}
|
|
|
|
impl MainWindow {
|
|
pub const LABEL: &str = "main";
|
|
|
|
pub fn create(app: &AppHandle) -> Result<Self, tauri::Error> {
|
|
if let Some(window) = app.get_webview_window(Self::LABEL) {
|
|
return Ok(Self(window));
|
|
}
|
|
|
|
let window_builder = base_window_config(
|
|
WebviewWindowBuilder::new(app, Self::LABEL, WebviewUrl::App("/".into())),
|
|
app,
|
|
)
|
|
.title("OpenCode")
|
|
.decorations(true)
|
|
.disable_drag_drop_handler()
|
|
.zoom_hotkeys_enabled(false)
|
|
.visible(true)
|
|
.maximized(true)
|
|
.initialization_script(format!(
|
|
r#"
|
|
window.__OPENCODE__ ??= {{}};
|
|
window.__OPENCODE__.updaterEnabled = {UPDATER_ENABLED};
|
|
"#
|
|
));
|
|
|
|
let window = window_builder.build()?;
|
|
|
|
setup_window_state_listener(app, &window);
|
|
|
|
#[cfg(windows)]
|
|
{
|
|
use tauri_plugin_decorum::WebviewWindowExt;
|
|
let _ = window.create_overlay_titlebar();
|
|
}
|
|
|
|
Ok(Self(window))
|
|
}
|
|
}
|
|
|
|
fn setup_window_state_listener(app: &AppHandle, window: &WebviewWindow) {
|
|
let (tx, mut rx) = mpsc::channel::<()>(1);
|
|
|
|
window.on_window_event(move |event| {
|
|
use tauri::WindowEvent;
|
|
if !matches!(event, WindowEvent::Moved(_) | WindowEvent::Resized(_)) {
|
|
return;
|
|
}
|
|
let _ = tx.try_send(());
|
|
});
|
|
|
|
tokio::spawn({
|
|
let app = app.clone();
|
|
|
|
async move {
|
|
let save = || {
|
|
let handle = app.clone();
|
|
let app = app.clone();
|
|
let _ = handle.run_on_main_thread(move || {
|
|
let _ = app.save_window_state(window_state_flags());
|
|
});
|
|
};
|
|
|
|
while rx.recv().await.is_some() {
|
|
tokio::time::sleep(Duration::from_millis(200)).await;
|
|
|
|
save();
|
|
}
|
|
}
|
|
});
|
|
}
|
|
|
|
pub struct LoadingWindow(WebviewWindow);
|
|
|
|
impl Deref for LoadingWindow {
|
|
type Target = WebviewWindow;
|
|
|
|
fn deref(&self) -> &Self::Target {
|
|
&self.0
|
|
}
|
|
}
|
|
|
|
impl LoadingWindow {
|
|
pub const LABEL: &str = "loading";
|
|
|
|
pub fn create(app: &AppHandle) -> Result<Self, tauri::Error> {
|
|
let window_builder = base_window_config(
|
|
WebviewWindowBuilder::new(app, Self::LABEL, tauri::WebviewUrl::App("/loading".into())),
|
|
app,
|
|
)
|
|
.center()
|
|
.resizable(false)
|
|
.inner_size(640.0, 480.0)
|
|
.visible(true);
|
|
|
|
Ok(Self(window_builder.build()?))
|
|
}
|
|
}
|
|
|
|
fn base_window_config<'a, R: Runtime, M: Manager<R>>(
|
|
window_builder: WebviewWindowBuilder<'a, R, M>,
|
|
_app: &AppHandle,
|
|
) -> WebviewWindowBuilder<'a, R, M> {
|
|
let window_builder = window_builder.decorations(true);
|
|
|
|
#[cfg(windows)]
|
|
let window_builder = window_builder
|
|
// Some VPNs set a global/system proxy that WebView2 applies even for loopback
|
|
// connections, which breaks the app's localhost sidecar server.
|
|
// Note: when setting additional args, we must re-apply wry's default
|
|
// `--disable-features=...` flags.
|
|
.additional_browser_args(
|
|
"--proxy-bypass-list=<-loopback> --disable-features=msWebOOUI,msPdfOOUI,msSmartScreenProtection",
|
|
)
|
|
.data_directory(_app.path().config_dir().expect("Failed to get config dir").join(_app.config().product_name.clone().unwrap()))
|
|
.decorations(false);
|
|
|
|
#[cfg(target_os = "macos")]
|
|
let window_builder = window_builder
|
|
.title_bar_style(tauri::TitleBarStyle::Overlay)
|
|
.hidden_title(true)
|
|
.traffic_light_position(tauri::LogicalPosition::new(12.0, 18.0));
|
|
|
|
window_builder
|
|
}
|