Compare commits
3 commits
48d773c0b3
...
61d90da409
| Author | SHA1 | Date | |
|---|---|---|---|
| 61d90da409 | |||
| 84b7cb63f9 | |||
| e2f1efef8c |
7 changed files with 1249 additions and 1048 deletions
File diff suppressed because it is too large
Load diff
|
|
@ -283,3 +283,10 @@ body.window-maximized .window-element {
|
||||||
background-color: var(--surface, #ffffff) !important;
|
background-color: var(--surface, #ffffff) !important;
|
||||||
opacity: 1 !important;
|
opacity: 1 !important;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* Fix theme dropdown background - use surface color to adapt to theme */
|
||||||
|
/* This overrides hardcoded black background from other CSS files */
|
||||||
|
#themeDropdown,
|
||||||
|
select.theme-dropdown {
|
||||||
|
background: var(--surface) !important;
|
||||||
|
}
|
||||||
|
|
|
||||||
|
|
@ -876,7 +876,7 @@
|
||||||
[data-theme="sentient"] input,
|
[data-theme="sentient"] input,
|
||||||
[data-theme="sentient"] textarea,
|
[data-theme="sentient"] textarea,
|
||||||
[data-theme="sentient"] select {
|
[data-theme="sentient"] select {
|
||||||
background: var(--input-bg);
|
background: var(--surface);
|
||||||
border: 1px solid var(--input-border);
|
border: 1px solid var(--input-border);
|
||||||
color: var(--text);
|
color: var(--text);
|
||||||
border-radius: 8px;
|
border-radius: 8px;
|
||||||
|
|
@ -884,6 +884,12 @@
|
||||||
transition: all 0.2s ease;
|
transition: all 0.2s ease;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* Ensure theme dropdown uses surface color in all themes */
|
||||||
|
[data-theme="sentient"] select.theme-dropdown,
|
||||||
|
[data-theme="sentient"] #themeDropdown {
|
||||||
|
background: var(--surface) !important;
|
||||||
|
}
|
||||||
|
|
||||||
[data-theme="sentient"] input:focus,
|
[data-theme="sentient"] input:focus,
|
||||||
[data-theme="sentient"] textarea:focus,
|
[data-theme="sentient"] textarea:focus,
|
||||||
[data-theme="sentient"] select:focus {
|
[data-theme="sentient"] select:focus {
|
||||||
|
|
|
||||||
File diff suppressed because it is too large
Load diff
|
|
@ -263,6 +263,22 @@ const ThemeManager = (() => {
|
||||||
primary: primary,
|
primary: primary,
|
||||||
});
|
});
|
||||||
updateDropdown();
|
updateDropdown();
|
||||||
|
|
||||||
|
// Fix theme dropdown background to use surface color
|
||||||
|
const themeDropdown = document.getElementById("themeDropdown");
|
||||||
|
if (themeDropdown) {
|
||||||
|
const surfaceColor = getComputedStyle(document.documentElement)
|
||||||
|
.getPropertyValue("--surface")
|
||||||
|
.trim();
|
||||||
|
if (surfaceColor) {
|
||||||
|
themeDropdown.style.setProperty(
|
||||||
|
"background",
|
||||||
|
surfaceColor,
|
||||||
|
"important",
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
subscribers.forEach((cb) => cb({ themeId: id, themeName: theme.name }));
|
subscribers.forEach((cb) => cb({ themeId: id, themeName: theme.name }));
|
||||||
}, 50);
|
}, 50);
|
||||||
};
|
};
|
||||||
|
|
|
||||||
|
|
@ -131,6 +131,12 @@ if (typeof window.WindowManager === "undefined") {
|
||||||
windowEl.style.zIndex = this.zIndexCounter++;
|
windowEl.style.zIndex = this.zIndexCounter++;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Update document title
|
||||||
|
const windowObj = this.openWindows.find((w) => w.id === id);
|
||||||
|
if (windowObj) {
|
||||||
|
document.title = `${windowObj.title} - General Bots`;
|
||||||
|
}
|
||||||
|
|
||||||
// Highlight taskbar icon
|
// Highlight taskbar icon
|
||||||
if (this.taskbarApps) {
|
if (this.taskbarApps) {
|
||||||
const icons = this.taskbarApps.querySelectorAll(".taskbar-icon");
|
const icons = this.taskbarApps.querySelectorAll(".taskbar-icon");
|
||||||
|
|
@ -156,7 +162,10 @@ if (typeof window.WindowManager === "undefined") {
|
||||||
this.openWindows = this.openWindows.filter((w) => w.id !== id);
|
this.openWindows = this.openWindows.filter((w) => w.id !== id);
|
||||||
if (this.activeWindowId === id) {
|
if (this.activeWindowId === id) {
|
||||||
this.activeWindowId = null;
|
this.activeWindowId = null;
|
||||||
// Optionally focus the next highest z-index window
|
// Reset title to default when all windows are closed
|
||||||
|
if (this.openWindows.length === 0) {
|
||||||
|
document.title = "General Bots Desktop";
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -220,7 +229,7 @@ if (typeof window.WindowManager === "undefined") {
|
||||||
const minibarHeight = 28;
|
const minibarHeight = 28;
|
||||||
|
|
||||||
windowEl.style.width = "100%";
|
windowEl.style.width = "100%";
|
||||||
windowEl.style.height = `calc(100% - ${taskbarHeight}px - ${minibarHeight}px)`;
|
windowEl.style.height = `calc(100% - ${minibarHeight}px)`;
|
||||||
windowEl.style.top = `${minibarHeight}px`;
|
windowEl.style.top = `${minibarHeight}px`;
|
||||||
windowEl.style.left = "0px";
|
windowEl.style.left = "0px";
|
||||||
windowObj.isMaximized = true;
|
windowObj.isMaximized = true;
|
||||||
|
|
|
||||||
|
|
@ -12,7 +12,7 @@
|
||||||
align-items: center;
|
align-items: center;
|
||||||
padding: 0 12px;
|
padding: 0 12px;
|
||||||
z-index: 9999;
|
z-index: 9999;
|
||||||
font-family: 'Fira Code', monospace;
|
font-family: "Fira Code", monospace;
|
||||||
}
|
}
|
||||||
|
|
||||||
.minibar-brand {
|
.minibar-brand {
|
||||||
|
|
@ -60,29 +60,113 @@
|
||||||
|
|
||||||
<div class="minibar" id="minibar">
|
<div class="minibar" id="minibar">
|
||||||
<div class="minibar-brand">
|
<div class="minibar-brand">
|
||||||
<svg class="minibar-brand-icon" viewBox="0 0 24 24" fill="none" stroke="#84d669" stroke-width="2">
|
<svg
|
||||||
|
class="minibar-brand-icon"
|
||||||
|
viewBox="0 0 24 24"
|
||||||
|
fill="none"
|
||||||
|
stroke="#84d669"
|
||||||
|
stroke-width="2"
|
||||||
|
>
|
||||||
<circle cx="12" cy="12" r="10" />
|
<circle cx="12" cy="12" r="10" />
|
||||||
<path d="M8 12l3 3 5-5" />
|
<path d="M8 12l3 3 5-5" />
|
||||||
</svg>
|
</svg>
|
||||||
<span>Agent Farm</span>
|
<span>General Bots</span>
|
||||||
</div>
|
</div>
|
||||||
<div class="minibar-actions" style="position: relative;">
|
<div class="minibar-actions" style="position: relative">
|
||||||
<button class="minibar-btn" title="Settings" type="button">⚙</button>
|
<button class="minibar-btn" title="Settings" type="button">⚙</button>
|
||||||
<div class="user-menu-container" style="position: relative;">
|
<div class="user-menu-container" style="position: relative">
|
||||||
<button class="minibar-btn" id="userAvatar" title="Account" type="button"
|
<button
|
||||||
style="border-radius: 50%; width: 22px; height: 22px; background: #ddd; color: #555; font-size: 11px; font-weight: bold; overflow: hidden; display: flex; align-items: center; justify-content: center; margin-left: 4px;"><span>U</span></button>
|
class="minibar-btn"
|
||||||
<div id="userDropdown"
|
id="userAvatar"
|
||||||
style="display: none; position: absolute; right: 0; top: 100%; margin-top: 4px; background: white; border: 1px solid #f0f1f2; border-radius: 6px; box-shadow: 0 4px 12px rgba(0,0,0,0.1); width: 220px; padding: 12px; z-index: 10000; flex-direction: column; gap: 8px;">
|
title="Account"
|
||||||
|
type="button"
|
||||||
|
style="
|
||||||
|
border-radius: 50%;
|
||||||
|
width: 22px;
|
||||||
|
height: 22px;
|
||||||
|
background: #ddd;
|
||||||
|
color: #555;
|
||||||
|
font-size: 11px;
|
||||||
|
font-weight: bold;
|
||||||
|
overflow: hidden;
|
||||||
|
display: flex;
|
||||||
|
align-items: center;
|
||||||
|
justify-content: center;
|
||||||
|
margin-left: 4px;
|
||||||
|
"
|
||||||
|
>
|
||||||
|
<span>U</span>
|
||||||
|
</button>
|
||||||
|
<div
|
||||||
|
id="userDropdown"
|
||||||
|
style="
|
||||||
|
display: none;
|
||||||
|
position: absolute;
|
||||||
|
right: 0;
|
||||||
|
top: 100%;
|
||||||
|
margin-top: 4px;
|
||||||
|
background: white;
|
||||||
|
border: 1px solid #f0f1f2;
|
||||||
|
border-radius: 6px;
|
||||||
|
box-shadow: 0 4px 12px rgba(0, 0, 0, 0.1);
|
||||||
|
width: 220px;
|
||||||
|
padding: 12px;
|
||||||
|
z-index: 10000;
|
||||||
|
flex-direction: column;
|
||||||
|
gap: 8px;
|
||||||
|
"
|
||||||
|
>
|
||||||
<div
|
<div
|
||||||
style="display: flex; flex-direction: column; border-bottom: 1px solid #f0f1f2; padding-bottom: 8px;">
|
style="
|
||||||
<span id="userName" style="font-weight: 600; color: #3b3b3b; font-size: 13px;">User</span>
|
display: flex;
|
||||||
<span id="userEmail" style="color: #888; font-size: 11px;">user@example.com</span>
|
flex-direction: column;
|
||||||
|
border-bottom: 1px solid #f0f1f2;
|
||||||
|
padding-bottom: 8px;
|
||||||
|
"
|
||||||
|
>
|
||||||
|
<span
|
||||||
|
id="userName"
|
||||||
|
style="
|
||||||
|
font-weight: 600;
|
||||||
|
color: #3b3b3b;
|
||||||
|
font-size: 13px;
|
||||||
|
"
|
||||||
|
>User</span
|
||||||
|
>
|
||||||
|
<span id="userEmail" style="color: #888; font-size: 11px"
|
||||||
|
>user@example.com</span
|
||||||
|
>
|
||||||
</div>
|
</div>
|
||||||
<a id="authAction" href="/auth/login.html"
|
<a
|
||||||
style="display: flex; align-items: center; gap: 6px; text-decoration: none; padding: 6px; border-radius: 4px; font-size: 12px; transition: background 0.15s; cursor: pointer; color: var(--primary, #84d669);">
|
id="authAction"
|
||||||
<svg id="authIcon" width="14" height="14" viewBox="0 0 24 24" fill="none" stroke="currentColor"
|
href="/auth/login.html"
|
||||||
stroke-width="2" stroke-linecap="round" stroke-linejoin="round">
|
style="
|
||||||
<path d="M15 3h4a2 2 0 0 1 2 2v14a2 2 0 0 1-2 2h-4"></path>
|
display: flex;
|
||||||
|
align-items: center;
|
||||||
|
gap: 6px;
|
||||||
|
text-decoration: none;
|
||||||
|
padding: 6px;
|
||||||
|
border-radius: 4px;
|
||||||
|
font-size: 12px;
|
||||||
|
transition: background 0.15s;
|
||||||
|
cursor: pointer;
|
||||||
|
color: var(--primary, #84d669);
|
||||||
|
"
|
||||||
|
>
|
||||||
|
<svg
|
||||||
|
id="authIcon"
|
||||||
|
width="14"
|
||||||
|
height="14"
|
||||||
|
viewBox="0 0 24 24"
|
||||||
|
fill="none"
|
||||||
|
stroke="currentColor"
|
||||||
|
stroke-width="2"
|
||||||
|
stroke-linecap="round"
|
||||||
|
stroke-linejoin="round"
|
||||||
|
>
|
||||||
|
<path
|
||||||
|
d="M15 3h4a2 2 0 0 1 2 2v14a2 2 0 0 1-2 2h-4"
|
||||||
|
></path>
|
||||||
<polyline points="10 17 15 12 21 12"></polyline>
|
<polyline points="10 17 15 12 21 12"></polyline>
|
||||||
<line x1="15" y1="12" x2="3" y2="12"></line>
|
<line x1="15" y1="12" x2="3" y2="12"></line>
|
||||||
</svg>
|
</svg>
|
||||||
|
|
@ -95,50 +179,71 @@
|
||||||
|
|
||||||
<script>
|
<script>
|
||||||
(function () {
|
(function () {
|
||||||
var avatar = document.getElementById('userAvatar');
|
var avatar = document.getElementById("userAvatar");
|
||||||
var dropdown = document.getElementById('userDropdown');
|
var dropdown = document.getElementById("userDropdown");
|
||||||
|
|
||||||
avatar.addEventListener('click', function (e) {
|
avatar.addEventListener("click", function (e) {
|
||||||
e.stopPropagation();
|
e.stopPropagation();
|
||||||
dropdown.style.display = dropdown.style.display === 'none' ? 'flex' : 'none';
|
dropdown.style.display =
|
||||||
|
dropdown.style.display === "none" ? "flex" : "none";
|
||||||
});
|
});
|
||||||
|
|
||||||
document.addEventListener('click', function (e) {
|
document.addEventListener("click", function (e) {
|
||||||
if (!e.target.closest('.user-menu-container')) {
|
if (!e.target.closest(".user-menu-container")) {
|
||||||
dropdown.style.display = 'none';
|
dropdown.style.display = "none";
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
// Trigger manual load or UI sync since minibar loads asynchronously via HTMX
|
// Trigger manual load or UI sync since minibar loads asynchronously via HTMX
|
||||||
setTimeout(function () {
|
setTimeout(function () {
|
||||||
var token = localStorage.getItem("gb-access-token") || sessionStorage.getItem("gb-access-token");
|
var token =
|
||||||
|
localStorage.getItem("gb-access-token") ||
|
||||||
|
sessionStorage.getItem("gb-access-token");
|
||||||
if (token) {
|
if (token) {
|
||||||
fetch("/api/auth/me", { headers: { Authorization: "Bearer " + token } })
|
fetch("/api/auth/me", {
|
||||||
.then(res => res.json())
|
headers: { Authorization: "Bearer " + token },
|
||||||
.then(user => {
|
})
|
||||||
document.getElementById('userName').textContent = user.display_name || user.first_name || user.username || "User";
|
.then((res) => res.json())
|
||||||
document.getElementById('userEmail').textContent = user.email || "";
|
.then((user) => {
|
||||||
|
document.getElementById("userName").textContent =
|
||||||
|
user.display_name ||
|
||||||
|
user.first_name ||
|
||||||
|
user.username ||
|
||||||
|
"User";
|
||||||
|
document.getElementById("userEmail").textContent =
|
||||||
|
user.email || "";
|
||||||
|
|
||||||
var btn = document.getElementById('authAction');
|
var btn = document.getElementById("authAction");
|
||||||
btn.href = "#";
|
btn.href = "#";
|
||||||
btn.style.color = "var(--error, #ef4444)";
|
btn.style.color = "var(--error, #ef4444)";
|
||||||
document.getElementById('authText').textContent = "Sign out";
|
document.getElementById("authText").textContent =
|
||||||
document.getElementById('authIcon').innerHTML = '<path d="M9 21H5a2 2 0 0 1-2-2V5a2 2 0 0 1 2-2h4"></path><polyline points="16 17 21 12 16 7"></polyline><line x1="21" y1="12" x2="9" y2="12"></line>';
|
"Sign out";
|
||||||
|
document.getElementById("authIcon").innerHTML =
|
||||||
|
'<path d="M9 21H5a2 2 0 0 1-2-2V5a2 2 0 0 1 2-2h4"></path><polyline points="16 17 21 12 16 7"></polyline><line x1="21" y1="12" x2="9" y2="12"></line>';
|
||||||
|
|
||||||
btn.onclick = function (e) {
|
btn.onclick = function (e) {
|
||||||
e.preventDefault();
|
e.preventDefault();
|
||||||
fetch("/api/auth/logout", { method: "POST" }).finally(function () {
|
fetch("/api/auth/logout", {
|
||||||
|
method: "POST",
|
||||||
|
}).finally(function () {
|
||||||
localStorage.removeItem("gb-access-token");
|
localStorage.removeItem("gb-access-token");
|
||||||
sessionStorage.removeItem("gb-access-token");
|
sessionStorage.removeItem("gb-access-token");
|
||||||
window.location.href = "/auth/login.html";
|
window.location.href = "/auth/login.html";
|
||||||
});
|
});
|
||||||
};
|
};
|
||||||
|
|
||||||
var initial = (user.display_name || user.username || "U").charAt(0).toUpperCase();
|
var initial = (
|
||||||
document.getElementById('userAvatar').innerHTML = '<span>' + initial + '</span>';
|
user.display_name ||
|
||||||
|
user.username ||
|
||||||
|
"U"
|
||||||
|
)
|
||||||
|
.charAt(0)
|
||||||
|
.toUpperCase();
|
||||||
|
document.getElementById("userAvatar").innerHTML =
|
||||||
|
"<span>" + initial + "</span>";
|
||||||
})
|
})
|
||||||
.catch(console.error);
|
.catch(console.error);
|
||||||
}
|
}
|
||||||
}, 500);
|
}, 500);
|
||||||
})();
|
})();
|
||||||
</script>
|
</script>
|
||||||
|
|
|
||||||
Loading…
Add table
Reference in a new issue