fix(stage-tamagotchi): onboarding white screen

Close #337
This commit is contained in:
Ayaka Neko
2025-08-01 15:44:05 +08:00
parent e1e0606bb8
commit 82ece364b4
6 changed files with 85 additions and 40 deletions
@@ -11,7 +11,7 @@ pub async fn open_settings_window(app: tauri::AppHandle) -> Result<(), tauri::Er
return Ok(());
}
settings::new_settings_window(&app)?;
settings::new_settings_window(&app, None)?;
Ok(())
}
@@ -23,7 +23,7 @@ pub async fn open_chat_window(app: tauri::AppHandle) -> Result<(), tauri::Error>
return Ok(());
}
chat::new_chat_window(&app)?;
chat::new_chat_window(&app, None)?;
Ok(())
}
@@ -35,7 +35,7 @@ pub async fn open_onboarding_window(app: tauri::AppHandle) -> Result<(), tauri::
return Ok(());
}
onboarding::new_onboarding_window(&app)?;
onboarding::new_onboarding_window(&app, None)?;
Ok(())
}
@@ -1,11 +1,14 @@
use std::path::Path;
use std::{path::Path, sync::Arc};
use anyhow::{Ok, Result};
#[cfg(target_os = "macos")]
use tauri::TitleBarStyle;
use tauri::{Runtime, WebviewUrl, WebviewWindowBuilder};
use tauri::{Runtime, WebviewUrl, WebviewWindowBuilder, webview::PageLoadPayload};
pub fn new_chat_window<R: Runtime>(app: &tauri::AppHandle<R>) -> Result<tauri::WebviewWindow<R>> {
pub fn new_chat_window<R: Runtime>(
app: &tauri::AppHandle<R>,
page_load_handler: Option<Arc<dyn Fn(tauri::WebviewWindow<R>, PageLoadPayload) + Send + Sync>>,
) -> Result<tauri::WebviewWindow<R>> {
let mut builder = WebviewWindowBuilder::new(
app,
"chat",
@@ -17,6 +20,12 @@ pub fn new_chat_window<R: Runtime>(app: &tauri::AppHandle<R>) -> Result<tauri::W
.transparent(false)
.accept_first_mouse(true);
if let Some(handler) = page_load_handler {
builder = builder.on_page_load(move |window, load| {
handler(window, load);
});
}
#[cfg(target_os = "macos")]
{
// macOS traffic light (red, yellow, green) position customization
@@ -1,12 +1,13 @@
use std::path::Path;
use std::{path::Path, sync::Arc};
use anyhow::{Ok, Result};
#[cfg(target_os = "macos")]
use tauri::TitleBarStyle;
use tauri::{Runtime, WebviewUrl, WebviewWindowBuilder};
use tauri::{Runtime, WebviewUrl, WebviewWindowBuilder, webview::PageLoadPayload};
pub fn new_onboarding_window<R: Runtime>(
app: &tauri::AppHandle<R>
app: &tauri::AppHandle<R>,
page_load_handler: Option<Arc<dyn Fn(tauri::WebviewWindow<R>, PageLoadPayload) + Send + Sync>>,
) -> Result<tauri::WebviewWindow<R>> {
let mut builder = WebviewWindowBuilder::new(
app,
@@ -19,6 +20,12 @@ pub fn new_onboarding_window<R: Runtime>(
.transparent(false)
.accept_first_mouse(true);
if let Some(handler) = page_load_handler {
builder = builder.on_page_load(move |window, load| {
handler(window, load);
});
}
#[cfg(target_os = "macos")]
{
// macOS traffic light (red, yellow, green) position customization
@@ -1,12 +1,13 @@
use std::path::Path;
use std::{path::Path, sync::Arc};
use anyhow::{Ok, Result};
#[cfg(target_os = "macos")]
use tauri::TitleBarStyle;
use tauri::{Runtime, WebviewUrl, WebviewWindowBuilder};
use tauri::{Runtime, WebviewUrl, WebviewWindowBuilder, webview::PageLoadPayload};
pub fn new_settings_window<R: Runtime>(
app: &tauri::AppHandle<R>
app: &tauri::AppHandle<R>,
page_load_handler: Option<Arc<dyn Fn(tauri::WebviewWindow<R>, PageLoadPayload) + Send + Sync>>,
) -> Result<tauri::WebviewWindow<R>> {
let mut builder = WebviewWindowBuilder::new(
app,
@@ -19,6 +20,12 @@ pub fn new_settings_window<R: Runtime>(
.transparent(false)
.accept_first_mouse(true);
if let Some(handler) = page_load_handler {
builder = builder.on_page_load(move |window, load| {
handler(window, load);
});
}
#[cfg(target_os = "macos")]
{
// macOS traffic light (red, yellow, green) position customization
+7 -7
View File
@@ -35,16 +35,16 @@ pub fn run() {
.plugin(tauri_plugin_window_pass_through_on_hover::init())
.plugin(tauri_plugin_window_router_link::init(
WindowMatcher::new()
.register("chat", |app| {
chat::new_chat_window(&app)
.register("chat", |app, on_page_load| {
chat::new_chat_window(&app, on_page_load)
.map_err(|e| e)
})
.register("settings", |app| {
settings::new_settings_window(&app)
.register("settings", |app, on_page_load| {
settings::new_settings_window(&app, on_page_load)
.map_err(|e| e)
})
.register("onboarding", |app| {
onboarding::new_onboarding_window(&app)
.register("onboarding", |app, on_page_load| {
onboarding::new_onboarding_window(&app, on_page_load)
.map_err(|e| e)
})
))
@@ -137,7 +137,7 @@ pub fn run() {
return;
}
app::windows::settings::new_settings_window(app).unwrap();
app::windows::settings::new_settings_window(app, None).unwrap();
}
"center" => {
let _ = app.get_webview_window("main")
@@ -1,4 +1,4 @@
use std::collections::HashMap;
use std::{collections::HashMap, sync::Arc};
use anyhow::Result;
#[cfg(debug_assertions)]
@@ -7,10 +7,15 @@ use tauri::{
Manager,
Runtime,
plugin::{Builder, TauriPlugin},
webview::{PageLoadEvent, PageLoadPayload},
};
pub type WindowCreator<R> =
Box<dyn Fn(tauri::AppHandle<R>) -> Result<tauri::WebviewWindow<R>> + Send + Sync>;
pub type PageLoadHandler<R> =
Option<Arc<dyn Fn(tauri::WebviewWindow<R>, PageLoadPayload) + Send + Sync>>;
pub type WindowCreator<R> = Box<
dyn Fn(tauri::AppHandle<R>, PageLoadHandler<R>) -> Result<tauri::WebviewWindow<R>> + Send + Sync,
>;
// Define a matcher struct that holds window creation logic
pub struct WindowMatcher<R: Runtime> {
@@ -30,7 +35,10 @@ impl<R: Runtime> WindowMatcher<R> {
creator: F,
) -> Self
where
F: Fn(tauri::AppHandle<R>) -> Result<tauri::WebviewWindow<R>> + Send + Sync + 'static,
F: Fn(tauri::AppHandle<R>, PageLoadHandler<R>) -> Result<tauri::WebviewWindow<R>>
+ Send
+ Sync
+ 'static,
{
self
.creators
@@ -42,6 +50,7 @@ impl<R: Runtime> WindowMatcher<R> {
&self,
app: tauri::AppHandle<R>,
label: &str,
custom_page_load_handler: PageLoadHandler<R>,
) -> Result<tauri::WebviewWindow<R>, String> {
// First try to get existing window
if let Some(window) = app.get_webview_window(label) {
@@ -50,9 +59,8 @@ impl<R: Runtime> WindowMatcher<R> {
// If no existing window, try to create one using registered creator
match self.creators.get(label) {
Some(creator) => {
creator(app).map_err(|e| format!("Failed to create {} window: {}", label, e))
},
Some(creator) => creator(app, custom_page_load_handler)
.map_err(|e| format!("Failed to create {} window: {}", label, e)),
None => Err(format!("Unknown window label: {}", label)),
}
}
@@ -69,23 +77,37 @@ async fn go<R: Runtime>(
) -> std::result::Result<(), String> {
let window_label = window_label.ok_or("Missing window label")?;
let matcher = app_handle.state::<WindowMatcher<R>>();
let target_window = matcher.get_or_create_window(app_handle.clone(), &window_label)?;
let mut current_url = target_window
.url()
.map_err(|e| format!("Failed to get current URL: {}", e))?;
let route: String = "/".to_string() + route.trim_start_matches('/');
current_url.set_fragment(Some(route.to_string().as_str()));
matcher.get_or_create_window(
app_handle.clone(),
&window_label,
Some(Arc::new(
move |target_window: tauri::WebviewWindow<R>, load| {
match load.event() {
PageLoadEvent::Finished => {
let current_url = target_window
.url()
.map_err(|e| format!("Failed to get current URL: {}", e));
if let Ok(mut current_url) = current_url {
let route: String = "/".to_string() + route.trim_start_matches('/');
current_url.set_fragment(Some(route.to_string().as_str()));
let _ = target_window.show();
if let Ok(url) = target_window.url() {
if url == current_url {
// If the URL is already the same, we don't need to navigate again.
return Ok(());
}
let _ = target_window.show();
if let Ok(url) = target_window.url() {
if url == current_url {
// If the URL is already the same, we don't need to navigate again.
return;
}
let _ = target_window.navigate(current_url);
}
let _ = target_window.navigate(current_url);
}
}
},
_ => {},
}
},
)),
)?;
Ok(())
}