Centralize shell bridge glue
This commit is contained in:
parent
147a09035c
commit
a9976c54ae
4 changed files with 103 additions and 46 deletions
|
|
@ -7777,7 +7777,7 @@
|
|||
<script src="https://cdn.jsdelivr.net/npm/chart.js@4/dist/chart.umd.min.js"></script>
|
||||
{{ vite_assets('body')|safe }}
|
||||
<script src="{{ url_for('static', filename='setup-wizard.js', v=static_v) }}"></script>
|
||||
<!-- Split modules (was: script.js) — core.js must load first, init.js last -->
|
||||
<!-- Split modules (was: script.js) — core.js must load first, init.js before shell-bridge.js -->
|
||||
<script src="{{ url_for('static', filename='core.js', v=static_v) }}"></script>
|
||||
<script src="{{ url_for('static', filename='shared-helpers.js', v=static_v) }}"></script>
|
||||
<script src="{{ url_for('static', filename='media-player.js', v=static_v) }}"></script>
|
||||
|
|
@ -7796,6 +7796,7 @@
|
|||
<script src="{{ url_for('static', filename='stats-automations.js', v=static_v) }}"></script>
|
||||
<script src="{{ url_for('static', filename='pages-extra.js', v=static_v) }}"></script>
|
||||
<script src="{{ url_for('static', filename='init.js', v=static_v) }}"></script>
|
||||
<script src="{{ url_for('static', filename='shell-bridge.js', v=static_v) }}"></script>
|
||||
<!-- Notification bell + floating helper toggle — always accessible above modals -->
|
||||
<!-- Ambient glow under the global search bar. Radial gradient, brightest
|
||||
directly under the bar, tapering out toward the window corners.
|
||||
|
|
|
|||
2
webui/src/platform/shell/globals.d.ts
vendored
2
webui/src/platform/shell/globals.d.ts
vendored
|
|
@ -30,7 +30,7 @@ declare global {
|
|||
};
|
||||
SoulSyncWebShellBridge?: {
|
||||
getCurrentPageId: () => ShellPageId;
|
||||
getCurrentProfileContext: () => ShellProfileContext;
|
||||
getCurrentProfileContext: () => ShellProfileContext | null;
|
||||
isPageAllowed: (pageId: ShellPageId) => boolean;
|
||||
getProfileHomePage: () => ShellPageId;
|
||||
resolveLegacyPath: (pathname: string) => ShellPageId | null;
|
||||
|
|
|
|||
|
|
@ -329,50 +329,6 @@ function activatePage(pageId, options = {}) {
|
|||
loadPageData(pageId);
|
||||
}
|
||||
|
||||
function activateLegacyPath(pathname) {
|
||||
const router = getWebRouter();
|
||||
const targetPage = router?.resolvePageId?.(pathname) || _getPageFromPath(pathname);
|
||||
if (!targetPage) return;
|
||||
|
||||
if (!isPageAllowed(targetPage)) {
|
||||
const home = getProfileHomePage();
|
||||
if (home !== targetPage) {
|
||||
navigateToPage(home, { replace: true });
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
activatePage(targetPage, { forceReload: true });
|
||||
}
|
||||
|
||||
const SHELL_BRIDGE_READY_EVENT = 'ss:webui-shell-bridge-ready';
|
||||
|
||||
window.SoulSyncWebShellBridge = {
|
||||
getCurrentPageId() {
|
||||
return currentPage || getWebRouter()?.resolvePageId?.(window.location.pathname) || _getPageFromPath();
|
||||
},
|
||||
getCurrentProfileContext() {
|
||||
return getCurrentProfileContext();
|
||||
},
|
||||
isPageAllowed(pageId) {
|
||||
return isPageAllowed(pageId);
|
||||
},
|
||||
getProfileHomePage() {
|
||||
return getProfileHomePage();
|
||||
},
|
||||
setActivePageChrome(pageId) {
|
||||
setActivePageChrome(pageId);
|
||||
},
|
||||
activateLegacyPath(pathname) {
|
||||
activateLegacyPath(pathname);
|
||||
},
|
||||
showReactHost(pageId) {
|
||||
showReactHost(pageId);
|
||||
},
|
||||
};
|
||||
|
||||
window.dispatchEvent(new CustomEvent(SHELL_BRIDGE_READY_EVENT));
|
||||
|
||||
function renderProfileAvatar(el, profile) {
|
||||
// Renders avatar as image (if avatar_url set) or colored initial fallback
|
||||
// Preserves existing classes, ensures 'profile-avatar' is present
|
||||
|
|
|
|||
100
webui/static/shell-bridge.js
Normal file
100
webui/static/shell-bridge.js
Normal file
|
|
@ -0,0 +1,100 @@
|
|||
// SoulSync shell bridge glue
|
||||
// Keep this file loaded after init.js so the legacy shell helpers it wraps
|
||||
// have already been defined.
|
||||
|
||||
function getWebRouter() {
|
||||
return window.SoulSyncWebRouter ?? null;
|
||||
}
|
||||
|
||||
function showLegacyPage(pageId) {
|
||||
document.querySelectorAll('.page').forEach(page => {
|
||||
page.classList.remove('active');
|
||||
});
|
||||
const page = document.getElementById(`${pageId}-page`);
|
||||
if (page) {
|
||||
page.classList.add('active');
|
||||
}
|
||||
const reactHost = document.getElementById('webui-react-root');
|
||||
if (reactHost) {
|
||||
reactHost.classList.remove('active');
|
||||
}
|
||||
}
|
||||
|
||||
function setActivePageChrome(pageId) {
|
||||
document.querySelectorAll('.nav-button').forEach(btn => {
|
||||
btn.classList.remove('active');
|
||||
});
|
||||
const navButton = document.querySelector(`[data-page="${pageId}"]`);
|
||||
if (navButton) {
|
||||
navButton.classList.add('active');
|
||||
}
|
||||
currentPage = pageId;
|
||||
if (typeof _gsUpdateVisibility === 'function') _gsUpdateVisibility();
|
||||
if (window.pageParticles && window._particlesEnabled !== false) window.pageParticles.setPage(pageId);
|
||||
if (window.workerOrbs) window.workerOrbs.setPage(pageId);
|
||||
}
|
||||
|
||||
function showReactHost(pageId) {
|
||||
document.querySelectorAll('.page').forEach(page => {
|
||||
page.classList.remove('active');
|
||||
});
|
||||
const host = document.getElementById('webui-react-root');
|
||||
if (host) {
|
||||
host.classList.add('active');
|
||||
}
|
||||
currentPage = pageId;
|
||||
if (typeof _gsUpdateVisibility === 'function') _gsUpdateVisibility();
|
||||
if (window.pageParticles && window._particlesEnabled !== false) window.pageParticles.setPage(pageId);
|
||||
if (window.workerOrbs) window.workerOrbs.setPage(pageId);
|
||||
}
|
||||
|
||||
function activateLegacyPath(pathname) {
|
||||
const router = getWebRouter();
|
||||
const targetPage = router?.resolvePageId?.(pathname) || _getPageFromPath(pathname);
|
||||
if (!targetPage) return;
|
||||
|
||||
if (!isPageAllowed(targetPage)) {
|
||||
const home = getProfileHomePage();
|
||||
if (home !== targetPage) {
|
||||
navigateToPage(home, { replace: true });
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
activatePage(targetPage, { forceReload: true });
|
||||
}
|
||||
|
||||
const SHELL_BRIDGE_READY_EVENT = 'ss:webui-shell-bridge-ready';
|
||||
|
||||
window.SoulSyncWebShellBridge = {
|
||||
getCurrentPageId() {
|
||||
return currentPage || getWebRouter()?.resolvePageId?.(window.location.pathname) || _getPageFromPath();
|
||||
},
|
||||
getCurrentProfileContext() {
|
||||
if (!currentProfile) return null;
|
||||
return {
|
||||
profileId: currentProfile.id,
|
||||
isAdmin: !!currentProfile.is_admin,
|
||||
};
|
||||
},
|
||||
isPageAllowed(pageId) {
|
||||
return isPageAllowed(pageId);
|
||||
},
|
||||
getProfileHomePage() {
|
||||
return getProfileHomePage();
|
||||
},
|
||||
resolveLegacyPath(pathname) {
|
||||
return getWebRouter()?.resolvePageId?.(pathname) ?? null;
|
||||
},
|
||||
setActivePageChrome(pageId) {
|
||||
setActivePageChrome(pageId);
|
||||
},
|
||||
activateLegacyPath(pathname) {
|
||||
activateLegacyPath(pathname);
|
||||
},
|
||||
showReactHost(pageId) {
|
||||
showReactHost(pageId);
|
||||
},
|
||||
};
|
||||
|
||||
window.dispatchEvent(new CustomEvent(SHELL_BRIDGE_READY_EVENT));
|
||||
Loading…
Reference in a new issue