feat: add dynamic window title updates
All checks were successful
BotUI CI / build (push) Successful in 2m48s
All checks were successful
BotUI CI / build (push) Successful in 2m48s
- Window title now shows current window name followed by 'General Bots'
- Title format: '{Window Name} - General Bots' (e.g., 'Chat - General Bots')
- Resets to 'General Bots Desktop' when all windows are closed
- Updated default title from 'BUILD V3 - Web Desktop Environment' to 'General Bots Desktop'
- Added cache-busting parameter to window-manager.js to ensure browser reloads updated code
This commit is contained in:
parent
84b7cb63f9
commit
61d90da409
2 changed files with 593 additions and 491 deletions
|
|
@ -1,10 +1,9 @@
|
|||
<!DOCTYPE html>
|
||||
<!doctype html>
|
||||
<html lang="en">
|
||||
|
||||
<head>
|
||||
<meta charset="UTF-8">
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
||||
<title>BUILD V3 - Web Desktop Environment</title>
|
||||
<meta charset="UTF-8" />
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
|
||||
<title>General Bots Desktop</title>
|
||||
|
||||
<!-- Link to the existing compiled CSS -->
|
||||
<link rel="stylesheet" href="/suite/css/app.css" />
|
||||
|
|
@ -14,7 +13,8 @@
|
|||
|
||||
<!-- Local JS requirements per AGENTS.md / UI.md -->
|
||||
<script src="/suite/js/vendor/htmx.min.js"></script>
|
||||
<script src="/suite/js/window-manager.js"></script>
|
||||
<script src="/suite/js/vendor/marked.min.js"></script>
|
||||
<script src="/suite/js/window-manager.js?v=2"></script>
|
||||
<script src="/suite/js/theme-manager.js"></script>
|
||||
|
||||
<style>
|
||||
|
|
@ -25,7 +25,7 @@
|
|||
}
|
||||
|
||||
body {
|
||||
font-family: 'Fira Code', 'Fira Sans', Arial, sans-serif;
|
||||
font-family: "Fira Code", "Fira Sans", Arial, sans-serif;
|
||||
background: var(--bg, #ffffff);
|
||||
color: var(--text, #333333);
|
||||
overflow: hidden;
|
||||
|
|
@ -83,7 +83,9 @@
|
|||
height: 30px;
|
||||
stroke: var(--text-secondary, #3b3b3b);
|
||||
opacity: 0.6;
|
||||
transition: stroke 0.15s ease, opacity 0.15s ease;
|
||||
transition:
|
||||
stroke 0.15s ease,
|
||||
opacity 0.15s ease;
|
||||
}
|
||||
|
||||
.sidebar-item:hover .sidebar-icon {
|
||||
|
|
@ -99,54 +101,7 @@
|
|||
overflow: hidden;
|
||||
}
|
||||
|
||||
/* Top Navigation Tabs */
|
||||
.tabs-container {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
background: var(--bg-secondary, #f8f8f8);
|
||||
border-bottom: 1px solid var(--border-color, #f0f1f2);
|
||||
z-index: 100;
|
||||
}
|
||||
|
||||
.tabs-row {
|
||||
display: flex;
|
||||
height: 34px;
|
||||
}
|
||||
|
||||
.main-tab {
|
||||
height: 34px;
|
||||
min-width: 169px;
|
||||
flex: 1;
|
||||
border-right: 1px solid var(--border-color, #f0f1f2);
|
||||
display: flex;
|
||||
align-items: center;
|
||||
padding: 0 18px;
|
||||
cursor: pointer;
|
||||
transition: background 0.15s ease;
|
||||
}
|
||||
|
||||
.main-tab:hover {
|
||||
background: var(--bg, #ffffff);
|
||||
}
|
||||
|
||||
.main-tab.active {
|
||||
background: var(--primary, #84d669);
|
||||
}
|
||||
|
||||
.main-tab.active .main-tab-content {
|
||||
color: var(--bg, #ffffff);
|
||||
}
|
||||
|
||||
.main-tab-content {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
gap: 4px;
|
||||
font-family: 'Fira Code', monospace;
|
||||
font-size: 14px;
|
||||
font-weight: 500;
|
||||
color: var(--text-secondary, #3b3b3b);
|
||||
transition: color 0.15s ease;
|
||||
}
|
||||
/* Top Navigation Tabs - Removed (already in Vibe) */
|
||||
|
||||
/* Workspace (Where windows float) */
|
||||
.workspace {
|
||||
|
|
@ -220,7 +175,7 @@
|
|||
}
|
||||
|
||||
.desktop-icon-label {
|
||||
font-family: 'Fira Code', monospace;
|
||||
font-family: "Fira Code", monospace;
|
||||
font-size: 12px;
|
||||
font-weight: 600;
|
||||
color: var(--text-secondary, #374151);
|
||||
|
|
@ -231,13 +186,13 @@
|
|||
text-align: center;
|
||||
}
|
||||
|
||||
.bg-grid { display: none; }
|
||||
|
||||
.bg-svg { display: none !important; }
|
||||
|
||||
|
||||
|
||||
.bg-grid {
|
||||
display: none;
|
||||
}
|
||||
|
||||
.bg-svg {
|
||||
display: none !important;
|
||||
}
|
||||
|
||||
/* Bottom Taskbar */
|
||||
.toolbar {
|
||||
|
|
@ -260,7 +215,7 @@
|
|||
}
|
||||
|
||||
.toolbar-time {
|
||||
font-family: 'Fira Code', monospace;
|
||||
font-family: "Fira Code", monospace;
|
||||
font-size: 14px;
|
||||
color: var(--text-secondary, #3b3b3b);
|
||||
text-align: right;
|
||||
|
|
@ -287,138 +242,211 @@
|
|||
|
||||
.taskbar-item.active {
|
||||
border-bottom-color: var(--primary, #84d669);
|
||||
background: linear-gradient(to bottom, transparent 50%, var(--primary-alpha-10, rgba(132, 214, 105, 0.1)) 100%);
|
||||
background: linear-gradient(
|
||||
to bottom,
|
||||
transparent 50%,
|
||||
var(--primary-alpha-10, rgba(132, 214, 105, 0.1)) 100%
|
||||
);
|
||||
}
|
||||
</style>
|
||||
</head>
|
||||
|
||||
<body>
|
||||
<!-- Minibar Component (Phase 8) -->
|
||||
<div hx-get="/suite/partials/minibar.html" hx-trigger="load" hx-swap="outerHTML"></div>
|
||||
<div
|
||||
hx-get="/suite/partials/minibar.html"
|
||||
hx-trigger="load"
|
||||
hx-swap="outerHTML"
|
||||
></div>
|
||||
|
||||
<div class="build-container">
|
||||
<!-- Left Sidebar -->
|
||||
<aside class="sidebar">
|
||||
<div class="sidebar-item active" title="Home">
|
||||
<svg class="sidebar-icon" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2">
|
||||
<path d="M3 9l9-7 9 7v11a2 2 0 0 1-2 2H5a2 2 0 0 1-2-2z"></path>
|
||||
<svg
|
||||
class="sidebar-icon"
|
||||
viewBox="0 0 24 24"
|
||||
fill="none"
|
||||
stroke="currentColor"
|
||||
stroke-width="2"
|
||||
>
|
||||
<path
|
||||
d="M3 9l9-7 9 7v11a2 2 0 0 1-2 2H5a2 2 0 0 1-2-2z"
|
||||
></path>
|
||||
<polyline points="9 22 9 12 15 12 15 22"></polyline>
|
||||
</svg>
|
||||
</div>
|
||||
<div class="sidebar-item" title="Search">
|
||||
<svg class="sidebar-icon" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2">
|
||||
<svg
|
||||
class="sidebar-icon"
|
||||
viewBox="0 0 24 24"
|
||||
fill="none"
|
||||
stroke="currentColor"
|
||||
stroke-width="2"
|
||||
>
|
||||
<circle cx="11" cy="11" r="8"></circle>
|
||||
<line x1="21" y1="21" x2="16.65" y2="16.65"></line>
|
||||
</svg>
|
||||
</div>
|
||||
<div class="sidebar-item" title="Terminal">
|
||||
<svg class="sidebar-icon" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2">
|
||||
<svg
|
||||
class="sidebar-icon"
|
||||
viewBox="0 0 24 24"
|
||||
fill="none"
|
||||
stroke="currentColor"
|
||||
stroke-width="2"
|
||||
>
|
||||
<polyline points="4 17 10 11 4 5"></polyline>
|
||||
<line x1="12" y1="19" x2="20" y2="19"></line>
|
||||
</svg>
|
||||
</div>
|
||||
<div class="sidebar-item" title="User">
|
||||
<svg class="sidebar-icon" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2">
|
||||
<path d="M20 21v-2a4 4 0 0 0-4-4H8a4 4 0 0 0-4 4v2"></path>
|
||||
<svg
|
||||
class="sidebar-icon"
|
||||
viewBox="0 0 24 24"
|
||||
fill="none"
|
||||
stroke="currentColor"
|
||||
stroke-width="2"
|
||||
>
|
||||
<path
|
||||
d="M20 21v-2a4 4 0 0 0-4-4H8a4 4 0 0 0-4 4v2"
|
||||
></path>
|
||||
<circle cx="12" cy="7" r="4"></circle>
|
||||
</svg>
|
||||
</div>
|
||||
<div class="sidebar-item" title="Apps">
|
||||
<svg class="sidebar-icon" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2">
|
||||
<svg
|
||||
class="sidebar-icon"
|
||||
viewBox="0 0 24 24"
|
||||
fill="none"
|
||||
stroke="currentColor"
|
||||
stroke-width="2"
|
||||
>
|
||||
<rect x="3" y="3" width="7" height="7"></rect>
|
||||
<rect x="14" y="3" width="7" height="7"></rect>
|
||||
<rect x="14" y="14" width="7" height="7"></rect>
|
||||
<rect x="3" y="14" width="7" height="7"></rect>
|
||||
</svg>
|
||||
</div>
|
||||
<div class="sidebar-item" style="margin-top: auto;" title="Settings">
|
||||
<svg class="sidebar-icon" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2">
|
||||
<div
|
||||
class="sidebar-item"
|
||||
style="margin-top: auto"
|
||||
title="Settings"
|
||||
>
|
||||
<svg
|
||||
class="sidebar-icon"
|
||||
viewBox="0 0 24 24"
|
||||
fill="none"
|
||||
stroke="currentColor"
|
||||
stroke-width="2"
|
||||
>
|
||||
<circle cx="12" cy="12" r="3"></circle>
|
||||
<path
|
||||
d="M19.4 15a1.65 1.65 0 0 0 .33 1.82l.06.06a2 2 0 0 1 0 2.83 2 2 0 0 1-2.83 0l-.06-.06a1.65 1.65 0 0 0-1.82-.33 1.65 1.65 0 0 0-1 1.51V21a2 2 0 0 1-2 2 2 2 0 0 1-2-2v-.09A1.65 1.65 0 0 0 9 19.4a1.65 1.65 0 0 0-1.82.33l-.06.06a2 2 0 0 1-2.83 0 2 2 0 0 1 0-2.83l.06-.06a1.65 1.65 0 0 0 .33-1.82 1.65 1.65 0 0 0-1.51-1H3a2 2 0 0 1-2-2 2 2 0 0 1 2-2h.09A1.65 1.65 0 0 0 4.6 9a1.65 1.65 0 0 0-.33-1.82l-.06-.06a2 2 0 0 1 0-2.83 2 2 0 0 1 2.83 0l.06.06a1.65 1.65 0 0 0 1.82.33H9a1.65 1.65 0 0 0 1-1.51V3a2 2 0 0 1 2-2 2 2 0 0 1 2 2v.09a1.65 1.65 0 0 0 1 1.51 1.65 1.65 0 0 0 1.82-.33l.06-.06a2 2 0 0 1 2.83 0 2 2 0 0 1 0 2.83l-.06.06a1.65 1.65 0 0 0-.33 1.82V9a1.65 1.65 0 0 0 1.51 1H21a2 2 0 0 1 2 2 2 2 0 0 1-2 2h-.09a1.65 1.65 0 0 0-1.51 1z">
|
||||
</path>
|
||||
d="M19.4 15a1.65 1.65 0 0 0 .33 1.82l.06.06a2 2 0 0 1 0 2.83 2 2 0 0 1-2.83 0l-.06-.06a1.65 1.65 0 0 0-1.82-.33 1.65 1.65 0 0 0-1 1.51V21a2 2 0 0 1-2 2 2 2 0 0 1-2-2v-.09A1.65 1.65 0 0 0 9 19.4a1.65 1.65 0 0 0-1.82.33l-.06.06a2 2 0 0 1-2.83 0 2 2 0 0 1 0-2.83l.06-.06a1.65 1.65 0 0 0 .33-1.82 1.65 1.65 0 0 0-1.51-1H3a2 2 0 0 1-2-2 2 2 0 0 1 2-2h.09A1.65 1.65 0 0 0 4.6 9a1.65 1.65 0 0 0-.33-1.82l-.06-.06a2 2 0 0 1 0-2.83 2 2 0 0 1 2.83 0l.06.06a1.65 1.65 0 0 0 1.82.33H9a1.65 1.65 0 0 0 1-1.51V3a2 2 0 0 1 2-2 2 2 0 0 1 2 2v.09a1.65 1.65 0 0 0 1 1.51 1.65 1.65 0 0 0 1.82-.33l.06-.06a2 2 0 0 1 2.83 0 2 2 0 0 1 0 2.83l-.06.06a1.65 1.65 0 0 0-.33 1.82V9a1.65 1.65 0 0 0 1.51 1H21a2 2 0 0 1 2 2 2 2 0 0 1-2 2h-.09a1.65 1.65 0 0 0-1.51 1z"
|
||||
></path>
|
||||
</svg>
|
||||
</div>
|
||||
</aside>
|
||||
|
||||
<!-- Main Wrapper -->
|
||||
<div class="main-wrapper">
|
||||
<!-- Top Navigation Tabs -->
|
||||
<div class="tabs-container">
|
||||
<div class="breadcrumb-row"
|
||||
style="display: flex; height: 34px; border-bottom: 1px solid var(--border-color, #f0f1f2); align-items: center; padding: 0 18px; font-family: 'Fira Code', monospace; font-size: 14px; color: var(--text-muted, #6b7280); gap: 8px;">
|
||||
<span style="color: var(--text-secondary, #374151);">// DASHBOARD</span>
|
||||
<span style="color: var(--text-muted, #9ca3af);">></span>
|
||||
<span style="color: var(--text, #374151); font-weight: 600;">// E-COMMERCE APP DEVELOPMENT</span>
|
||||
</div>
|
||||
<div class="tabs-row">
|
||||
<div class="main-tab">
|
||||
<div class="main-tab-content"><span>//</span><span>PLAN</span></div>
|
||||
</div>
|
||||
<div class="main-tab active">
|
||||
<div class="main-tab-content"><span>//</span><span>BUILD</span></div>
|
||||
</div>
|
||||
<div class="main-tab">
|
||||
<div class="main-tab-content"><span>//</span><span>REVIEW</span></div>
|
||||
</div>
|
||||
<div class="main-tab">
|
||||
<div class="main-tab-content"><span>//</span><span>DEPLOY</span></div>
|
||||
</div>
|
||||
<div class="main-tab">
|
||||
<div class="main-tab-content"><span>//</span><span>MONITOR</span></div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<!-- Top Navigation Tabs - Removed (already in Vibe) -->
|
||||
|
||||
<!-- Workspace container where WindowManager operates -->
|
||||
<div class="workspace" id="desktop-content">
|
||||
|
||||
<!-- Background Pattern -->
|
||||
|
||||
|
||||
|
||||
<div class="panel-section">
|
||||
<div class="desktop-icons-container">
|
||||
|
||||
<div class="desktop-icon" data-app-id="vibe" data-app-title="Vibe"
|
||||
hx-get="/suite/partials/vibe.html" hx-swap="none">
|
||||
<div
|
||||
class="desktop-icon"
|
||||
data-app-id="vibe"
|
||||
data-app-title="Vibe"
|
||||
hx-get="/suite/partials/vibe.html"
|
||||
hx-swap="none"
|
||||
>
|
||||
<div class="app-icon">
|
||||
<svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2"
|
||||
stroke-linecap="round" stroke-linejoin="round">
|
||||
<path d="M12 2v20M17 5H9.5a3.5 3.5 0 0 0 0 7h5a3.5 3.5 0 0 1 0 7H6" />
|
||||
<svg
|
||||
viewBox="0 0 24 24"
|
||||
fill="none"
|
||||
stroke="currentColor"
|
||||
stroke-width="2"
|
||||
stroke-linecap="round"
|
||||
stroke-linejoin="round"
|
||||
>
|
||||
<path
|
||||
d="M12 2v20M17 5H9.5a3.5 3.5 0 0 0 0 7h5a3.5 3.5 0 0 1 0 7H6"
|
||||
/>
|
||||
</svg>
|
||||
</div>
|
||||
<span class="desktop-icon-label">Vibe</span>
|
||||
</div>
|
||||
|
||||
<div class="desktop-icon" data-app-id="tasks" data-app-title="Tasks"
|
||||
hx-get="/suite/tasks/task-window.html" hx-swap="none">
|
||||
<div
|
||||
class="desktop-icon"
|
||||
data-app-id="tasks"
|
||||
data-app-title="Tasks"
|
||||
hx-get="/suite/tasks/task-window.html"
|
||||
hx-swap="none"
|
||||
>
|
||||
<div class="app-icon">
|
||||
<svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2"
|
||||
stroke-linecap="round" stroke-linejoin="round">
|
||||
<svg
|
||||
viewBox="0 0 24 24"
|
||||
fill="none"
|
||||
stroke="currentColor"
|
||||
stroke-width="2"
|
||||
stroke-linecap="round"
|
||||
stroke-linejoin="round"
|
||||
>
|
||||
<path d="M9 11l3 3L22 4" />
|
||||
<path d="M21 12v7a2 2 0 0 1-2 2H5a2 2 0 0 1-2-2V5a2 2 0 0 1 2-2h11" />
|
||||
<path
|
||||
d="M21 12v7a2 2 0 0 1-2 2H5a2 2 0 0 1-2-2V5a2 2 0 0 1 2-2h11"
|
||||
/>
|
||||
</svg>
|
||||
</div>
|
||||
<span class="desktop-icon-label">Tasks</span>
|
||||
</div>
|
||||
|
||||
<div class="desktop-icon" data-app-id="chat" data-app-title="Chat"
|
||||
hx-get="/suite/partials/chat.html" hx-swap="none">
|
||||
<div
|
||||
class="desktop-icon"
|
||||
data-app-id="chat"
|
||||
data-app-title="Chat"
|
||||
hx-get="/suite/partials/chat.html"
|
||||
hx-swap="none"
|
||||
>
|
||||
<div class="app-icon">
|
||||
<svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2"
|
||||
stroke-linecap="round" stroke-linejoin="round">
|
||||
<path d="M21 15a2 2 0 0 1-2 2H7l-4 4V5a2 2 0 0 1 2-2h14a2 2 0 0 1 2 2z" />
|
||||
<svg
|
||||
viewBox="0 0 24 24"
|
||||
fill="none"
|
||||
stroke="currentColor"
|
||||
stroke-width="2"
|
||||
stroke-linecap="round"
|
||||
stroke-linejoin="round"
|
||||
>
|
||||
<path
|
||||
d="M21 15a2 2 0 0 1-2 2H7l-4 4V5a2 2 0 0 1 2-2h14a2 2 0 0 1 2 2z"
|
||||
/>
|
||||
</svg>
|
||||
</div>
|
||||
<span class="desktop-icon-label">Chat</span>
|
||||
</div>
|
||||
|
||||
<div class="desktop-icon" data-app-id="terminal" data-app-title="Terminal"
|
||||
hx-get="/suite/terminal/terminal.html" hx-swap="none">
|
||||
<div
|
||||
class="desktop-icon"
|
||||
data-app-id="terminal"
|
||||
data-app-title="Terminal"
|
||||
hx-get="/suite/terminal/terminal.html"
|
||||
hx-swap="none"
|
||||
>
|
||||
<div class="app-icon">
|
||||
<svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2"
|
||||
stroke-linecap="round" stroke-linejoin="round">
|
||||
<svg
|
||||
viewBox="0 0 24 24"
|
||||
fill="none"
|
||||
stroke="currentColor"
|
||||
stroke-width="2"
|
||||
stroke-linecap="round"
|
||||
stroke-linejoin="round"
|
||||
>
|
||||
<polyline points="4 17 10 11 4 5" />
|
||||
<line x1="12" y1="19" x2="20" y2="19" />
|
||||
</svg>
|
||||
|
|
@ -426,23 +454,46 @@
|
|||
<span class="desktop-icon-label">Terminal</span>
|
||||
</div>
|
||||
|
||||
<div class="desktop-icon" data-app-id="drive" data-app-title="Explorer"
|
||||
hx-get="/suite/drive/drive.html" hx-swap="none">
|
||||
<div
|
||||
class="desktop-icon"
|
||||
data-app-id="drive"
|
||||
data-app-title="Explorer"
|
||||
hx-get="/suite/drive/drive.html"
|
||||
hx-swap="none"
|
||||
>
|
||||
<div class="app-icon">
|
||||
<svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2"
|
||||
stroke-linecap="round" stroke-linejoin="round">
|
||||
<svg
|
||||
viewBox="0 0 24 24"
|
||||
fill="none"
|
||||
stroke="currentColor"
|
||||
stroke-width="2"
|
||||
stroke-linecap="round"
|
||||
stroke-linejoin="round"
|
||||
>
|
||||
<path
|
||||
d="M22 19a2 2 0 0 1-2 2H4a2 2 0 0 1-2-2V5a2 2 0 0 1 2-2h5l2 3h9a2 2 0 0 1 2 2z" />
|
||||
d="M22 19a2 2 0 0 1-2 2H4a2 2 0 0 1-2-2V5a2 2 0 0 1 2-2h5l2 3h9a2 2 0 0 1 2 2z"
|
||||
/>
|
||||
</svg>
|
||||
</div>
|
||||
<span class="desktop-icon-label">Explorer</span>
|
||||
</div>
|
||||
|
||||
<div class="desktop-icon" data-app-id="editor" data-app-title="Editor"
|
||||
hx-get="/suite/editor.html" hx-swap="none">
|
||||
<div
|
||||
class="desktop-icon"
|
||||
data-app-id="editor"
|
||||
data-app-title="Editor"
|
||||
hx-get="/suite/editor.html"
|
||||
hx-swap="none"
|
||||
>
|
||||
<div class="app-icon">
|
||||
<svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2"
|
||||
stroke-linecap="round" stroke-linejoin="round">
|
||||
<svg
|
||||
viewBox="0 0 24 24"
|
||||
fill="none"
|
||||
stroke="currentColor"
|
||||
stroke-width="2"
|
||||
stroke-linecap="round"
|
||||
stroke-linejoin="round"
|
||||
>
|
||||
<polyline points="16 18 22 12 16 6" />
|
||||
<polyline points="8 6 2 12 8 18" />
|
||||
</svg>
|
||||
|
|
@ -450,18 +501,30 @@
|
|||
<span class="desktop-icon-label">Editor</span>
|
||||
</div>
|
||||
|
||||
<div class="desktop-icon" data-app-id="browser" data-app-title="Browser"
|
||||
hx-get="/suite/browser/browser.html" hx-swap="none">
|
||||
<div
|
||||
class="desktop-icon"
|
||||
data-app-id="browser"
|
||||
data-app-title="Browser"
|
||||
hx-get="/suite/browser/browser.html"
|
||||
hx-swap="none"
|
||||
>
|
||||
<div class="app-icon">
|
||||
<svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2"
|
||||
stroke-linecap="round" stroke-linejoin="round">
|
||||
<svg
|
||||
viewBox="0 0 24 24"
|
||||
fill="none"
|
||||
stroke="currentColor"
|
||||
stroke-width="2"
|
||||
stroke-linecap="round"
|
||||
stroke-linejoin="round"
|
||||
>
|
||||
<circle cx="12" cy="12" r="10" />
|
||||
<polygon points="16.24 7.76 14.12 14.12 7.76 16.24 9.88 9.88 16.24 7.76" />
|
||||
<polygon
|
||||
points="16.24 7.76 14.12 14.12 7.76 16.24 9.88 9.88 16.24 7.76"
|
||||
/>
|
||||
</svg>
|
||||
</div>
|
||||
<span class="desktop-icon-label">Browser</span>
|
||||
</div>
|
||||
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
|
@ -471,9 +534,12 @@
|
|||
<div id="taskbar-apps">
|
||||
<!-- Taskbar items populated automatically by window-manager.js -->
|
||||
</div>
|
||||
<div class="toolbar-time" style="display: flex; align-items: center; gap: 15px;">
|
||||
<div
|
||||
class="toolbar-time"
|
||||
style="display: flex; align-items: center; gap: 15px"
|
||||
>
|
||||
<div id="themeSelectorContainer"></div>
|
||||
<div style="text-align: right;">
|
||||
<div style="text-align: right">
|
||||
<div id="clock-time">00:00</div>
|
||||
<div id="clock-date">01/01/2026</div>
|
||||
</div>
|
||||
|
|
@ -484,28 +550,49 @@
|
|||
|
||||
<!-- HTMX Intercepts and WindowManager Init as described in UI.md Phase 3 -->
|
||||
<script>
|
||||
document.addEventListener('DOMContentLoaded', () => {
|
||||
document.addEventListener("DOMContentLoaded", async () => {
|
||||
// Initialize WindowManager
|
||||
if (typeof window.WindowManager !== 'undefined') {
|
||||
if (typeof window.WindowManager !== "undefined") {
|
||||
window.wm = window.WindowManager;
|
||||
} else {
|
||||
console.error("WindowManager class not loaded from window-manager.js");
|
||||
console.error(
|
||||
"WindowManager class not loaded from window-manager.js",
|
||||
);
|
||||
}
|
||||
|
||||
// Initialize ThemeManager
|
||||
if (typeof window.ThemeManager !== 'undefined') {
|
||||
if (typeof window.ThemeManager !== "undefined") {
|
||||
window.ThemeManager.init();
|
||||
}
|
||||
|
||||
// Auto-open Chat window maximized on desktop load
|
||||
if (window.wm) {
|
||||
try {
|
||||
const response = await fetch(
|
||||
"/suite/partials/chat.html",
|
||||
);
|
||||
if (response.ok) {
|
||||
const htmlContent = await response.text();
|
||||
window.wm.open("chat", "Chat", htmlContent);
|
||||
// Maximize the chat window after opening
|
||||
setTimeout(() => {
|
||||
window.wm.toggleMaximize("chat");
|
||||
}, 100);
|
||||
}
|
||||
} catch (err) {
|
||||
console.error("Failed to auto-open chat:", err);
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
// Listen to HTMX afterRequest event
|
||||
document.body.addEventListener('htmx:afterRequest', function (evt) {
|
||||
document.body.addEventListener("htmx:afterRequest", function (evt) {
|
||||
const target = evt.detail.elt;
|
||||
|
||||
// Check if the click came from a desktop icon
|
||||
if (target.classList.contains('desktop-icon')) {
|
||||
const appId = target.getAttribute('data-app-id');
|
||||
const title = target.getAttribute('data-app-title');
|
||||
if (target.classList.contains("desktop-icon")) {
|
||||
const appId = target.getAttribute("data-app-id");
|
||||
const title = target.getAttribute("data-app-title");
|
||||
const htmlContent = evt.detail.xhr.response;
|
||||
|
||||
// Tell WindowManager to open it
|
||||
|
|
@ -516,7 +603,9 @@
|
|||
|
||||
// Ensure Theme dropdown is re-injected if wiped
|
||||
if (window.ThemeManager) {
|
||||
const container = document.getElementById('themeSelectorContainer');
|
||||
const container = document.getElementById(
|
||||
"themeSelectorContainer",
|
||||
);
|
||||
if (container && !container.hasChildNodes()) {
|
||||
// Quick and dirty way to re-init
|
||||
window.ThemeManager.init();
|
||||
|
|
@ -527,10 +616,14 @@
|
|||
// Simple Clock implementation matching the screenshot bottom right corner
|
||||
setInterval(() => {
|
||||
const now = new Date();
|
||||
document.getElementById('clock-time').textContent = now.toLocaleTimeString([], { hour: '2-digit', minute: '2-digit' });
|
||||
document.getElementById('clock-date').textContent = now.toLocaleDateString();
|
||||
document.getElementById("clock-time").textContent =
|
||||
now.toLocaleTimeString([], {
|
||||
hour: "2-digit",
|
||||
minute: "2-digit",
|
||||
});
|
||||
document.getElementById("clock-date").textContent =
|
||||
now.toLocaleDateString();
|
||||
}, 1000);
|
||||
</script>
|
||||
</body>
|
||||
|
||||
</html>
|
||||
|
|
@ -131,6 +131,12 @@ if (typeof window.WindowManager === "undefined") {
|
|||
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
|
||||
if (this.taskbarApps) {
|
||||
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);
|
||||
if (this.activeWindowId === id) {
|
||||
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;
|
||||
|
||||
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.left = "0px";
|
||||
windowObj.isMaximized = true;
|
||||
|
|
|
|||
Loading…
Add table
Reference in a new issue