191 lines
6.3 KiB
JavaScript
Executable File
191 lines
6.3 KiB
JavaScript
Executable File
// Soleprint Sidebar - Self-Injecting Script
|
|
// Matches the original Jinja2 sidebar look
|
|
|
|
(function () {
|
|
"use strict";
|
|
|
|
const SPR_BASE = "/spr";
|
|
|
|
let config = null;
|
|
let user = null;
|
|
|
|
let expanded = localStorage.getItem("spr_sidebar_expanded") === "true";
|
|
|
|
// Icons as SVG strings
|
|
const icons = {
|
|
toggle: `<svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2">
|
|
<rect x="3" y="3" width="18" height="18" rx="2"/>
|
|
<path d="M9 3v18M3 9h6"/>
|
|
</svg>`,
|
|
home: `<svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2">
|
|
<path d="M3 12l9-9 9 9M5 10v10a1 1 0 001 1h3m10-11v10a1 1 0 01-1 1h-3m-6 0a1 1 0 001-1v-4a1 1 0 011-1h2a1 1 0 011 1v4a1 1 0 001 1"/>
|
|
</svg>`,
|
|
soleprint: `<svg viewBox="0 0 24 24" fill="currentColor">
|
|
<ellipse cx="8" cy="10" rx="3" ry="5" transform="rotate(-10 8 10)"/>
|
|
<ellipse cx="8" cy="17" rx="2.5" ry="3" transform="rotate(-10 8 17)"/>
|
|
<ellipse cx="16" cy="8" rx="3" ry="5" transform="rotate(10 16 8)"/>
|
|
<ellipse cx="16" cy="15" rx="2.5" ry="3" transform="rotate(10 16 15)"/>
|
|
</svg>`,
|
|
artery: `<svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2">
|
|
<path d="M12 2v8M12 10L6 18M12 10l6 8"/>
|
|
<circle cx="12" cy="10" r="2"/>
|
|
</svg>`,
|
|
atlas: `<svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2">
|
|
<circle cx="12" cy="12" r="8"/>
|
|
<path d="M12 4v16M4 12h16"/>
|
|
</svg>`,
|
|
station: `<svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2">
|
|
<rect x="4" y="6" width="16" height="12" rx="1"/>
|
|
<circle cx="9" cy="11" r="2"/>
|
|
<circle cx="15" cy="11" r="2"/>
|
|
</svg>`,
|
|
google: `<svg viewBox="0 0 24 24">
|
|
<path fill="#4285F4" d="M22.56 12.25c0-.78-.07-1.53-.2-2.25H12v4.26h5.92c-.26 1.37-1.04 2.53-2.21 3.31v2.77h3.57c2.08-1.92 3.28-4.74 3.28-8.09z"/>
|
|
<path fill="#34A853" d="M12 23c2.97 0 5.46-.98 7.28-2.66l-3.57-2.77c-.98.66-2.23 1.06-3.71 1.06-2.86 0-5.29-1.93-6.16-4.53H2.18v2.84C3.99 20.53 7.7 23 12 23z"/>
|
|
<path fill="#FBBC05" d="M5.84 14.09c-.22-.66-.35-1.36-.35-2.09s.13-1.43.35-2.09V7.07H2.18C1.43 8.55 1 10.22 1 12s.43 3.45 1.18 4.93l2.85-2.22.81-.62z"/>
|
|
<path fill="#EA4335" d="M12 5.38c1.62 0 3.06.56 4.21 1.64l3.15-3.15C17.45 2.09 14.97 1 12 1 7.7 1 3.99 3.47 2.18 7.07l3.66 2.84c.87-2.6 3.3-4.53 6.16-4.53z"/>
|
|
</svg>`,
|
|
user: `<svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2">
|
|
<circle cx="12" cy="8" r="4"/>
|
|
<path d="M4 20c0-4 4-6 8-6s8 2 8 6"/>
|
|
</svg>`,
|
|
logout: `<svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2">
|
|
<path d="M9 21H5a2 2 0 01-2-2V5a2 2 0 012-2h4M16 17l5-5-5-5M21 12H9"/>
|
|
</svg>`,
|
|
};
|
|
|
|
async function init() {
|
|
try {
|
|
// Load config
|
|
const response = await fetch(`${SPR_BASE}/api/sidebar/config`);
|
|
config = await response.json();
|
|
|
|
// Check auth status
|
|
await checkAuth();
|
|
|
|
// Create sidebar
|
|
createSidebar();
|
|
|
|
console.log("[Soleprint] Sidebar initialized for room:", config.room);
|
|
} catch (error) {
|
|
console.error("[Soleprint] Failed to initialize sidebar:", error);
|
|
}
|
|
}
|
|
|
|
async function checkAuth() {
|
|
if (!config.auth_enabled) return;
|
|
|
|
try {
|
|
const response = await fetch(`${SPR_BASE}/artery/google/oauth/status`, {
|
|
credentials: "include",
|
|
});
|
|
const data = await response.json();
|
|
if (data.authenticated) {
|
|
user = data.user;
|
|
}
|
|
} catch (error) {
|
|
console.log("[Soleprint] Auth check failed:", error);
|
|
}
|
|
}
|
|
|
|
function createSidebar() {
|
|
// Add body class
|
|
document.body.classList.add("spr-sidebar-active");
|
|
if (expanded) {
|
|
document.body.classList.add("spr-sidebar-expanded");
|
|
}
|
|
|
|
const sidebar = document.createElement("nav");
|
|
sidebar.id = "spr-sidebar";
|
|
if (expanded) sidebar.classList.add("expanded");
|
|
|
|
sidebar.innerHTML = `
|
|
<button class="spr-sidebar-item spr-toggle" title="Toggle sidebar">
|
|
${icons.toggle}
|
|
<span class="label">Menu</span>
|
|
<span class="tooltip">Toggle</span>
|
|
</button>
|
|
|
|
<a href="/" class="spr-sidebar-item" title="${config.room}">
|
|
${icons.home}
|
|
<span class="label">${config.room}</span>
|
|
<span class="tooltip">${config.room}</span>
|
|
</a>
|
|
|
|
<div class="spr-sidebar-divider"></div>
|
|
|
|
<a href="${SPR_BASE}/" class="spr-sidebar-item active" title="Soleprint">
|
|
${icons.soleprint}
|
|
<span class="label">Soleprint</span>
|
|
<span class="tooltip">Soleprint</span>
|
|
</a>
|
|
|
|
<div class="spr-sidebar-divider"></div>
|
|
|
|
<div class="spr-sidebar-icon" title="Artery">
|
|
${icons.artery}
|
|
</div>
|
|
|
|
<div class="spr-sidebar-icon" title="Atlas">
|
|
${icons.atlas}
|
|
</div>
|
|
|
|
<div class="spr-sidebar-icon" title="Station">
|
|
${icons.station}
|
|
</div>
|
|
|
|
<div class="spr-sidebar-spacer"></div>
|
|
|
|
${config.auth_enabled ? renderAuthSection() : ""}
|
|
`;
|
|
|
|
// Add toggle click handler
|
|
sidebar
|
|
.querySelector(".spr-toggle")
|
|
.addEventListener("click", toggleSidebar);
|
|
|
|
document.body.appendChild(sidebar);
|
|
}
|
|
|
|
function toggleSidebar() {
|
|
const sidebar = document.getElementById("spr-sidebar");
|
|
expanded = !expanded;
|
|
sidebar.classList.toggle("expanded", expanded);
|
|
document.body.classList.toggle("spr-sidebar-expanded", expanded);
|
|
localStorage.setItem("spr_sidebar_expanded", expanded);
|
|
}
|
|
|
|
function renderAuthSection() {
|
|
if (user) {
|
|
return `
|
|
<div class="spr-sidebar-user">
|
|
<a href="${config.auth.logout_url}" class="spr-sidebar-item" title="Logout (${user.email})">
|
|
${icons.logout}
|
|
<span class="label">Logout</span>
|
|
<span class="tooltip">Logout</span>
|
|
</a>
|
|
</div>
|
|
`;
|
|
} else {
|
|
return `
|
|
<div class="spr-sidebar-user">
|
|
<a href="${config.auth.login_url}" class="spr-sidebar-item" title="Login with Google">
|
|
${icons.google}
|
|
<span class="label">Login</span>
|
|
<span class="tooltip">Login</span>
|
|
</a>
|
|
</div>
|
|
`;
|
|
}
|
|
}
|
|
|
|
// Initialize when DOM is ready
|
|
if (document.readyState === "loading") {
|
|
document.addEventListener("DOMContentLoaded", init);
|
|
} else {
|
|
init();
|
|
}
|
|
|
|
console.log("[Soleprint] Sidebar script loaded");
|
|
})();
|