fix(shell): coordinate startup cover and tab stills
This commit is contained in:
parent
fd99901bb2
commit
2008967c04
13 changed files with 442 additions and 52 deletions
|
|
@ -52,6 +52,8 @@ pub struct AppConfig {
|
|||
pub min_window_size: (f64, f64),
|
||||
/// The window's color before the shell paints (no white flash).
|
||||
pub background: (u8, u8, u8),
|
||||
/// Wait for the shell's `shell_ready` command before showing the first window.
|
||||
pub defer_window_show: bool,
|
||||
/// The shell draws the titlebar (Windows/Linux: frameless; macOS: an overlay titlebar with the
|
||||
/// traffic lights over the shell). Off: the OS frame, for a shell without one.
|
||||
pub custom_titlebar: bool,
|
||||
|
|
@ -74,6 +76,7 @@ impl AppConfig {
|
|||
window_size: (1360.0, 900.0),
|
||||
min_window_size: (900.0, 560.0),
|
||||
background: (7, 8, 12),
|
||||
defer_window_show: false,
|
||||
custom_titlebar: true,
|
||||
deep_link: false,
|
||||
updater: false,
|
||||
|
|
@ -319,8 +322,8 @@ async fn tabs_sync(webview: Webview, app: AppHandle, items: Vec<TabLayout>, view
|
|||
// and the app's per-tab state goes with the old one.
|
||||
let existing = match existing {
|
||||
Some(tab) if current_profile.as_deref() != Some(item.profile.as_str()) => {
|
||||
host::forget_tab(&app, &label);
|
||||
let _ = tab.close();
|
||||
host::forget_tab(&label);
|
||||
profiles(&app)?.tab_profiles.remove(&label);
|
||||
hooks.tab_closed(&app, &label, TabClosed::Replaced);
|
||||
None
|
||||
|
|
@ -383,8 +386,8 @@ async fn tabs_sync(webview: Webview, app: AppHandle, items: Vec<TabLayout>, view
|
|||
if let Some(id) = policy::tab_id(existing.label()) {
|
||||
if !keep.contains(id) {
|
||||
let label = existing.label().to_owned();
|
||||
host::forget_tab(&app, &label);
|
||||
let _ = existing.close();
|
||||
host::forget_tab(&label);
|
||||
if let Ok(mut data) = profiles(&app) {
|
||||
data.tab_profiles.remove(&label);
|
||||
}
|
||||
|
|
@ -423,6 +426,25 @@ async fn shell_focus(webview: Webview) -> Result<(), String> {
|
|||
webview.set_focus().map_err(|error| format!("FOCUS: {error}"))
|
||||
}
|
||||
|
||||
/// The shell calls this after its first DOM commit, so startup never exposes an empty webview.
|
||||
#[tauri::command]
|
||||
async fn shell_ready(webview: Webview, app: AppHandle) -> Result<(), String> {
|
||||
shell_only(&webview)?;
|
||||
app.get_window(policy::MAIN_LABEL)
|
||||
.ok_or("WINDOW: main window missing")?
|
||||
.show()
|
||||
.map_err(|error| format!("WINDOW: {error}"))
|
||||
}
|
||||
|
||||
/// The shell has committed a captured tab frame; its native webview can now be hidden.
|
||||
#[tauri::command]
|
||||
async fn tab_still_ready(webview: Webview, app: AppHandle, id: String, token: u64) -> Result<(), String> {
|
||||
shell_only(&webview)?;
|
||||
if !policy::valid_tab_id(&id) { return Err("VALIDATION: invalid tab id".into()); }
|
||||
host::acknowledge_still(&app, &id, token);
|
||||
Ok(())
|
||||
}
|
||||
|
||||
/// Raises the shell above the tab webviews while one of its overlays (menu, dialog, palette,
|
||||
/// drag) is open, so the panes stay on screen under it, or lowers it again. Returns whether this
|
||||
/// platform can; when not, the shell hides the tabs for the overlay instead.
|
||||
|
|
@ -701,6 +723,8 @@ fn host_handler() -> impl Fn(tauri::ipc::Invoke<Wry>) -> bool + Send + Sync + 's
|
|||
tab_action,
|
||||
open_external_url,
|
||||
shell_focus,
|
||||
shell_ready,
|
||||
tab_still_ready,
|
||||
shell_raise,
|
||||
window_system_menu,
|
||||
profiles_get,
|
||||
|
|
@ -864,6 +888,18 @@ fn open_window(app: &mut tauri::App<Wry>, config: &AppConfig) -> Result<(), Box<
|
|||
let shell = shell.transparent(true);
|
||||
let shell = window.add_child(shell, LogicalPosition::new(0.0, 0.0), LogicalSize::new(size.width, size.height))?;
|
||||
host::attach_shell(&shell);
|
||||
window.show()?;
|
||||
if config.defer_window_show {
|
||||
// A shell that opts in shows the window after initial layout and sync. If JS fails to
|
||||
// start, make the failure visible rather than leaving a hidden process.
|
||||
let fallback = window.clone();
|
||||
std::thread::spawn(move || {
|
||||
std::thread::sleep(std::time::Duration::from_secs(3));
|
||||
if fallback.is_visible().is_ok_and(|visible| !visible) {
|
||||
let _ = fallback.show();
|
||||
}
|
||||
});
|
||||
} else {
|
||||
window.show()?;
|
||||
}
|
||||
Ok(())
|
||||
}
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue