mirror of
https://github.com/Psychotoxical/psysonic.git
synced 2026-07-21 14:55:43 +00:00
fix(tray): blank Mainstage after cold-start minimized to tray (#1303)
This commit is contained in:
+7
-1
@@ -163,6 +163,12 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
|
|||||||
|
|
||||||
## Fixed
|
## Fixed
|
||||||
|
|
||||||
|
### Tray — blank Mainstage after cold start minimized to tray
|
||||||
|
|
||||||
|
**By [@cucadmuh](https://github.com/cucadmuh), PR [#1303](https://github.com/Psychotoxical/psysonic/pull/1303)**
|
||||||
|
|
||||||
|
* With **Start minimized to tray** enabled, the main content area could stay blank after opening from the tray (sidebar and queue rendered, Mainstage did not) until a manual tray hide/show cycle — `PAUSE_RENDERING_JS` on cold start froze Mainstage's `animate-fade-in` at `opacity: 0`. Cold-start tray now hides without pausing animations, `startup-splash-reveal.js` proactively hides when the tray flag is set, Mainstage drops the entrance fade, and showing the window resumes rendering.
|
||||||
|
|
||||||
### Tray — release build compile after #1296
|
### Tray — release build compile after #1296
|
||||||
|
|
||||||
**By [@cucadmuh](https://github.com/cucadmuh), PR [#1298](https://github.com/Psychotoxical/psysonic/pull/1298)**
|
**By [@cucadmuh](https://github.com/cucadmuh), PR [#1298](https://github.com/Psychotoxical/psysonic/pull/1298)**
|
||||||
@@ -173,7 +179,7 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
|
|||||||
|
|
||||||
**By [@cucadmuh](https://github.com/cucadmuh), PR [#1296](https://github.com/Psychotoxical/psysonic/pull/1296)**
|
**By [@cucadmuh](https://github.com/cucadmuh), PR [#1296](https://github.com/Psychotoxical/psysonic/pull/1296)**
|
||||||
|
|
||||||
* With **Start minimized to tray** enabled, opening the main window from the tray could leave the left sidebar menu invisible until a full app restart (seen on Linux tiling WMs such as Hyprland). The sidebar no longer uses a slide-in entrance animation that starts at `opacity: 0`; cold-start tray hide restores the original pause-and-hide path from PR #1271, and tray show again resumes rendering before `show()` without an extra `unminimize()` that could pop the window on tiling WMs.
|
* With **Start minimized to tray** enabled, opening the main window from the tray could leave the left sidebar menu invisible until a full app restart (seen on Linux tiling WMs such as Hyprland). The sidebar no longer uses a slide-in entrance animation that starts at `opacity: 0`; tray show resumes rendering before `show()` without an extra `unminimize()` that could pop the window on tiling WMs.
|
||||||
|
|
||||||
### Playlist and radio custom covers blank
|
### Playlist and radio custom covers blank
|
||||||
|
|
||||||
|
|||||||
@@ -1,5 +1,7 @@
|
|||||||
/**
|
/**
|
||||||
* Show the native window after the inline startup splash has painted.
|
* Show the native window after the inline startup splash has painted.
|
||||||
|
* When starting minimized to tray, hide the main window as early as possible
|
||||||
|
* (visible:false may still map briefly on some Linux WMs before this script).
|
||||||
* __TAURI_INTERNALS__ may not exist yet when this script first runs.
|
* __TAURI_INTERNALS__ may not exist yet when this script first runs.
|
||||||
*/
|
*/
|
||||||
(function startupSplashReveal() {
|
(function startupSplashReveal() {
|
||||||
@@ -12,8 +14,22 @@
|
|||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
function tryHideMainWindow() {
|
||||||
|
var internals = window.__TAURI_INTERNALS__;
|
||||||
|
if (!internals || typeof internals.invoke !== 'function') return false;
|
||||||
|
internals.invoke('plugin:window|hide', { label: 'main' }).catch(function () {});
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
function reveal(attempt) {
|
function reveal(attempt) {
|
||||||
if (window.__psyStartMinimizedToTray) return;
|
if (window.__psyStartMinimizedToTray) {
|
||||||
|
if (tryHideMainWindow()) return;
|
||||||
|
if (attempt >= MAX_ATTEMPTS) return;
|
||||||
|
window.setTimeout(function () {
|
||||||
|
reveal(attempt + 1);
|
||||||
|
}, 50);
|
||||||
|
return;
|
||||||
|
}
|
||||||
if (tryShowMainWindow()) return;
|
if (tryShowMainWindow()) return;
|
||||||
if (attempt >= MAX_ATTEMPTS) return;
|
if (attempt >= MAX_ATTEMPTS) return;
|
||||||
window.setTimeout(function () {
|
window.setTimeout(function () {
|
||||||
@@ -21,6 +37,18 @@
|
|||||||
}, 50);
|
}, 50);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (window.__psyStartMinimizedToTray) {
|
||||||
|
// Mark this synchronously, before React mounts. This deliberately does
|
||||||
|
// not set the CSS animation-pause attribute: entrance animations may
|
||||||
|
// still mount while the native window is hidden.
|
||||||
|
window.__psyHidden = true;
|
||||||
|
try {
|
||||||
|
sessionStorage.setItem('psy-startup-tray-handled', '1');
|
||||||
|
} catch (_err) {}
|
||||||
|
reveal(0);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
requestAnimationFrame(function () {
|
requestAnimationFrame(function () {
|
||||||
requestAnimationFrame(function () {
|
requestAnimationFrame(function () {
|
||||||
reveal(0);
|
reveal(0);
|
||||||
|
|||||||
@@ -906,28 +906,6 @@ pub fn run() {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
.on_page_load(|webview, payload| {
|
|
||||||
if webview.label() != "main" {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
match payload.event() {
|
|
||||||
tauri::webview::PageLoadEvent::Started => {
|
|
||||||
let app = webview.app_handle().clone();
|
|
||||||
std::thread::spawn(move || {
|
|
||||||
std::thread::sleep(std::time::Duration::from_millis(48));
|
|
||||||
if let Some(window) = app.get_webview_window("main") {
|
|
||||||
crate::lib_commands::ui::mini::eval_startup_main_window_visibility(&window);
|
|
||||||
}
|
|
||||||
});
|
|
||||||
}
|
|
||||||
tauri::webview::PageLoadEvent::Finished => {
|
|
||||||
if let Some(window) = webview.app_handle().get_webview_window("main") {
|
|
||||||
crate::lib_commands::ui::mini::eval_startup_main_window_visibility(&window);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
})
|
|
||||||
.invoke_handler(tauri::generate_handler![
|
.invoke_handler(tauri::generate_handler![
|
||||||
greet,
|
greet,
|
||||||
theme_import::import_theme_zip,
|
theme_import::import_theme_zip,
|
||||||
|
|||||||
@@ -169,46 +169,6 @@ document.documentElement.style.removeProperty('--psy-anim-speed');
|
|||||||
})();
|
})();
|
||||||
"#;
|
"#;
|
||||||
|
|
||||||
/// Show the main window after startup splash paint, or pause rendering and hide
|
|
||||||
/// when the user chose "start minimized to tray" (flag set in
|
|
||||||
/// `startup-splash-preflight.js`).
|
|
||||||
///
|
|
||||||
/// The shell no longer uses entrance animations that start at `opacity: 0`, so
|
|
||||||
/// pausing CSS here is safe on WebKitGTK tiling WMs (sidebar fix in #1296).
|
|
||||||
pub(crate) fn eval_startup_main_window_visibility(window: &tauri::WebviewWindow) {
|
|
||||||
let js = format!(
|
|
||||||
"(function () {{
|
|
||||||
try {{
|
|
||||||
if (sessionStorage.getItem('psy-startup-tray-handled') === '1') return;
|
|
||||||
}} catch (e) {{}}
|
|
||||||
var deferToTray = !!window.__psyStartMinimizedToTray;
|
|
||||||
if (!deferToTray) {{
|
|
||||||
try {{
|
|
||||||
var raw = localStorage.getItem('psysonic-auth');
|
|
||||||
if (raw) {{
|
|
||||||
var state = JSON.parse(raw).state;
|
|
||||||
deferToTray = !!(state && state.startMinimizedToTray && state.showTrayIcon !== false);
|
|
||||||
}}
|
|
||||||
}} catch (e) {{}}
|
|
||||||
}}
|
|
||||||
var internals = window.__TAURI_INTERNALS__;
|
|
||||||
if (deferToTray) {{
|
|
||||||
{pause}
|
|
||||||
try {{ sessionStorage.setItem('psy-startup-tray-handled', '1'); }} catch (e) {{}}
|
|
||||||
if (internals && typeof internals.invoke === 'function') {{
|
|
||||||
internals.invoke('plugin:window|hide', {{ label: 'main' }}).catch(function () {{}});
|
|
||||||
}}
|
|
||||||
return;
|
|
||||||
}}
|
|
||||||
if (internals && typeof internals.invoke === 'function') {{
|
|
||||||
internals.invoke('plugin:window|show', {{ label: 'main' }}).catch(function () {{}});
|
|
||||||
}}
|
|
||||||
}})();",
|
|
||||||
pause = PAUSE_RENDERING_JS.trim(),
|
|
||||||
);
|
|
||||||
let _ = window.eval(&js);
|
|
||||||
}
|
|
||||||
|
|
||||||
/// Resume rendering and bring the main window to the foreground.
|
/// Resume rendering and bring the main window to the foreground.
|
||||||
pub(crate) fn restore_main_window(main: &tauri::WebviewWindow) -> Result<(), String> {
|
pub(crate) fn restore_main_window(main: &tauri::WebviewWindow) -> Result<(), String> {
|
||||||
main.eval(RESUME_RENDERING_JS).map_err(|e| e.to_string())?;
|
main.eval(RESUME_RENDERING_JS).map_err(|e| e.to_string())?;
|
||||||
|
|||||||
@@ -345,7 +345,12 @@ export default function Home() {
|
|||||||
// sidebar) instead of leaving the user on nothing.
|
// sidebar) instead of leaving the user on nothing.
|
||||||
const allSectionsHidden = homeSections.every(s => !s.visible);
|
const allSectionsHidden = homeSections.every(s => !s.visible);
|
||||||
return (
|
return (
|
||||||
<div className={`animate-fade-in${homeLiteArtworkFx ? ' home-lite-artwork' : ''}${homeFlatArtworkClip ? ' home-flat-artwork-clip' : ''}`}>
|
<div
|
||||||
|
className={[
|
||||||
|
homeLiteArtworkFx ? 'home-lite-artwork' : '',
|
||||||
|
homeFlatArtworkClip ? 'home-flat-artwork-clip' : '',
|
||||||
|
].filter(Boolean).join(' ') || undefined}
|
||||||
|
>
|
||||||
{!loading && !perfFlags.disableMainstageHero && isVisible('hero') && <Hero albums={heroAlbums} />}
|
{!loading && !perfFlags.disableMainstageHero && isVisible('hero') && <Hero albums={heroAlbums} />}
|
||||||
|
|
||||||
<div className="content-body" style={{ display: 'flex', flexDirection: 'column', gap: '3rem' }}>
|
<div className="content-body" style={{ display: 'flex', flexDirection: 'column', gap: '3rem' }}>
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
const AUTH_STORAGE_KEY = 'psysonic-auth';
|
const AUTH_STORAGE_KEY = 'psysonic-auth';
|
||||||
|
|
||||||
/** Keep in sync with `public/startup-splash-preflight.js` and Rust `eval_startup_main_window_visibility`. */
|
/** Keep in sync with `public/startup-splash-preflight.js` and `public/startup-splash-reveal.js`. */
|
||||||
export const STARTUP_TRAY_HANDLED_KEY = 'psy-startup-tray-handled';
|
export const STARTUP_TRAY_HANDLED_KEY = 'psy-startup-tray-handled';
|
||||||
|
|
||||||
/** Read persisted "start minimized to tray" before Zustand rehydrates. */
|
/** Read persisted "start minimized to tray" before Zustand rehydrates. */
|
||||||
|
|||||||
Reference in New Issue
Block a user