// THIS FILE MUST BE ENTIRELY SELF-CONTAINED! DO NOT USE PACKAGES!
interface Window {
FocusNavController: any;
GamepadNavTree: any;
deckyFallbackLoaded?: boolean;
}
(async () => {
try {
if (window.deckyFallbackLoaded) return;
window.deckyFallbackLoaded = true;
// #region utils
function sleep(ms: number) {
return new Promise((res) => setTimeout(res, ms));
}
// #endregion
// #region DeckyIcon
const fallbackIcon = `
`;
// #endregion
// #region findSP
// from @decky/ui
function getFocusNavController(): any {
return window.GamepadNavTree?.m_context?.m_controller || window.FocusNavController;
}
function getGamepadNavigationTrees(): any {
const focusNav = getFocusNavController();
const context = focusNav.m_ActiveContext || focusNav.m_LastActiveContext;
return context?.m_rgGamepadNavigationTrees;
}
function findSP(): Window {
// old (SP as host)
if (document.title == 'SP') return window;
// new (SP as popup)
const navTrees = getGamepadNavigationTrees();
return navTrees?.find((x: any) => x.m_ID == 'root_1_').Root.Element.ownerDocument.defaultView;
}
// #endregion
const fallbackCSS = `
.fallbackContainer {
width: 100vw;
height: 100vh;
display: flex;
align-items: center;
justify-content: center;
text-align: center;
flex-direction: column;
z-index: 99999999;
pointer-events: none;
position: absolute;
top: 0;
left: 0;
backdrop-filter: blur(8px) brightness(40%);
}
.fallbackDeckyIcon {
width: 96px;
height: 96px;
padding-bottom: 1rem;
}
`;
const fallbackHTML = `
${fallbackIcon}
A crash loop has been detected and Decky has been disabled for this boot.
Steam will restart in 10 seconds...
`;
await sleep(4000);
const win = findSP() || window;
const container = Object.assign(document.createElement('div'), {
innerHTML: fallbackHTML,
});
container.classList.add('fallbackContainer');
win.document.body.appendChild(container);
await sleep(10000);
SteamClient.User.StartShutdown(false);
} catch (e) {
console.error('Error showing fallback!', e);
}
})();