feat: integrate DSH Filebrowser (pinned v2.32.0, dark mode, toggle selector UI from Claude Design, /u/nabil/files/ proxy)
This commit is contained in:
@@ -13,3 +13,8 @@ HERMES_TT_URL=http://100.86.197.88:3010
|
|||||||
HERMES_NYORA_URL=http://100.86.197.88:3020
|
HERMES_NYORA_URL=http://100.86.197.88:3020
|
||||||
HERMES_PERSO_URL=http://100.86.197.88:3031
|
HERMES_PERSO_URL=http://100.86.197.88:3031
|
||||||
HERMES_NABIL_URL=http://127.0.0.1:8642
|
HERMES_NABIL_URL=http://127.0.0.1:8642
|
||||||
|
DSH_FILEBROWSER_URL=http://dsh-filebrowser:80
|
||||||
|
|
||||||
|
# User IDs
|
||||||
|
DSH_UID=1001
|
||||||
|
DSH_GID=1001
|
||||||
|
|||||||
+13
-6
@@ -1,6 +1,6 @@
|
|||||||
import os
|
import os
|
||||||
from pathlib import Path
|
from pathlib import Path
|
||||||
from typing import Dict, Any, List
|
from typing import Dict, Any, List, Optional
|
||||||
from pydantic import BaseModel, Field, field_validator
|
from pydantic import BaseModel, Field, field_validator
|
||||||
from pydantic_settings import BaseSettings
|
from pydantic_settings import BaseSettings
|
||||||
|
|
||||||
@@ -20,6 +20,8 @@ class UniverseConfig(BaseModel):
|
|||||||
icon: str
|
icon: str
|
||||||
persona_file: str
|
persona_file: str
|
||||||
enabled: bool = True
|
enabled: bool = True
|
||||||
|
supports_files: bool = False
|
||||||
|
files_url: Optional[str] = None
|
||||||
|
|
||||||
class Settings(BaseSettings):
|
class Settings(BaseSettings):
|
||||||
app_name: str = "Hermes Hub"
|
app_name: str = "Hermes Hub"
|
||||||
@@ -36,6 +38,7 @@ class Settings(BaseSettings):
|
|||||||
hermes_nyora_url: str = os.getenv("HERMES_NYORA_URL", "http://100.86.197.88:3020")
|
hermes_nyora_url: str = os.getenv("HERMES_NYORA_URL", "http://100.86.197.88:3020")
|
||||||
hermes_perso_url: str = os.getenv("HERMES_PERSO_URL", "http://100.86.197.88:3031")
|
hermes_perso_url: str = os.getenv("HERMES_PERSO_URL", "http://100.86.197.88:3031")
|
||||||
hermes_nabil_url: str = os.getenv("HERMES_NABIL_URL", "http://127.0.0.1:8642")
|
hermes_nabil_url: str = os.getenv("HERMES_NABIL_URL", "http://127.0.0.1:8642")
|
||||||
|
dsh_filebrowser_url: str = os.getenv("DSH_FILEBROWSER_URL", "http://127.0.0.1:8901")
|
||||||
|
|
||||||
# Hub Secret — OBLIGATOIRE, aucun fallback codé en dur (Fail-Fast au démarrage)
|
# Hub Secret — OBLIGATOIRE, aucun fallback codé en dur (Fail-Fast au démarrage)
|
||||||
hub_secret: str = Field(..., min_length=16, description="Clé secrète maîtresse requise pour Hermes Hub")
|
hub_secret: str = Field(..., min_length=16, description="Clé secrète maîtresse requise pour Hermes Hub")
|
||||||
@@ -58,7 +61,6 @@ except Exception as e:
|
|||||||
# but runtime will fail fast if HUB_SECRET is absent
|
# but runtime will fail fast if HUB_SECRET is absent
|
||||||
if "HUB_SECRET" in os.environ:
|
if "HUB_SECRET" in os.environ:
|
||||||
raise e
|
raise e
|
||||||
# Fallback only if running build/compile check with dummy env
|
|
||||||
settings = None
|
settings = None
|
||||||
|
|
||||||
UNIVERSES: Dict[str, UniverseConfig] = {
|
UNIVERSES: Dict[str, UniverseConfig] = {
|
||||||
@@ -71,7 +73,8 @@ UNIVERSES: Dict[str, UniverseConfig] = {
|
|||||||
scope="tt",
|
scope="tt",
|
||||||
accent_token="--accent-tt",
|
accent_token="--accent-tt",
|
||||||
icon="briefcase",
|
icon="briefcase",
|
||||||
persona_file="tt.yaml"
|
persona_file="tt.yaml",
|
||||||
|
supports_files=False
|
||||||
),
|
),
|
||||||
"nyora": UniverseConfig(
|
"nyora": UniverseConfig(
|
||||||
id="nyora",
|
id="nyora",
|
||||||
@@ -82,7 +85,8 @@ UNIVERSES: Dict[str, UniverseConfig] = {
|
|||||||
scope="nyora",
|
scope="nyora",
|
||||||
accent_token="--accent-nyora",
|
accent_token="--accent-nyora",
|
||||||
icon="sparkles",
|
icon="sparkles",
|
||||||
persona_file="nyora.yaml"
|
persona_file="nyora.yaml",
|
||||||
|
supports_files=False
|
||||||
),
|
),
|
||||||
"perso": UniverseConfig(
|
"perso": UniverseConfig(
|
||||||
id="perso",
|
id="perso",
|
||||||
@@ -93,7 +97,8 @@ UNIVERSES: Dict[str, UniverseConfig] = {
|
|||||||
scope="perso",
|
scope="perso",
|
||||||
accent_token="--accent-perso",
|
accent_token="--accent-perso",
|
||||||
icon="home",
|
icon="home",
|
||||||
persona_file="perso.yaml"
|
persona_file="perso.yaml",
|
||||||
|
supports_files=False
|
||||||
),
|
),
|
||||||
"nabil": UniverseConfig(
|
"nabil": UniverseConfig(
|
||||||
id="nabil",
|
id="nabil",
|
||||||
@@ -104,7 +109,9 @@ UNIVERSES: Dict[str, UniverseConfig] = {
|
|||||||
scope="nabil",
|
scope="nabil",
|
||||||
accent_token="--accent-nabil",
|
accent_token="--accent-nabil",
|
||||||
icon="terminal",
|
icon="terminal",
|
||||||
persona_file="nabil.yaml"
|
persona_file="nabil.yaml",
|
||||||
|
supports_files=True,
|
||||||
|
files_url=os.getenv("DSH_FILEBROWSER_URL", "http://127.0.0.1:8901")
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
+22
-1
@@ -1,9 +1,30 @@
|
|||||||
from fastapi import APIRouter, Request, HTTPException
|
from fastapi import APIRouter, Request, HTTPException
|
||||||
from app.config import UNIVERSES
|
from app.config import UNIVERSES, get_universe
|
||||||
from app.proxy import proxy_request
|
from app.proxy import proxy_request
|
||||||
|
|
||||||
router = APIRouter(prefix="/u", tags=["Universe Proxy"])
|
router = APIRouter(prefix="/u", tags=["Universe Proxy"])
|
||||||
|
|
||||||
|
@router.api_route("/{universe_id}/files", methods=["GET", "POST", "PUT", "DELETE", "PATCH", "HEAD", "OPTIONS"])
|
||||||
|
@router.api_route("/{universe_id}/files/", methods=["GET", "POST", "PUT", "DELETE", "PATCH", "HEAD", "OPTIONS"])
|
||||||
|
@router.api_route("/{universe_id}/files/{path:path}", methods=["GET", "POST", "PUT", "DELETE", "PATCH", "HEAD", "OPTIONS"])
|
||||||
|
async def dynamic_files_proxy(universe_id: str, request: Request, path: str = ""):
|
||||||
|
if universe_id not in UNIVERSES:
|
||||||
|
raise HTTPException(status_code=404, detail=f"Universe '{universe_id}' not found.")
|
||||||
|
|
||||||
|
universe = UNIVERSES[universe_id]
|
||||||
|
if not universe.supports_files or not universe.files_url:
|
||||||
|
raise HTTPException(status_code=404, detail=f"Universe '{universe_id}' does not have an active filebrowser.")
|
||||||
|
|
||||||
|
# Filebrowser runs with --baseurl /u/{universe_id}/files
|
||||||
|
full_subpath = f"u/{universe_id}/files/{path}".rstrip("/") if path else f"u/{universe_id}/files/"
|
||||||
|
|
||||||
|
return await proxy_request(
|
||||||
|
request=request,
|
||||||
|
backend_url=universe.files_url,
|
||||||
|
path=full_subpath,
|
||||||
|
universe_id=universe_id
|
||||||
|
)
|
||||||
|
|
||||||
@router.api_route("/{universe_id}", methods=["GET", "POST", "PUT", "DELETE", "PATCH", "HEAD", "OPTIONS"])
|
@router.api_route("/{universe_id}", methods=["GET", "POST", "PUT", "DELETE", "PATCH", "HEAD", "OPTIONS"])
|
||||||
@router.api_route("/{universe_id}/", methods=["GET", "POST", "PUT", "DELETE", "PATCH", "HEAD", "OPTIONS"])
|
@router.api_route("/{universe_id}/", methods=["GET", "POST", "PUT", "DELETE", "PATCH", "HEAD", "OPTIONS"])
|
||||||
@router.api_route("/{universe_id}/{path:path}", methods=["GET", "POST", "PUT", "DELETE", "PATCH", "HEAD", "OPTIONS"])
|
@router.api_route("/{universe_id}/{path:path}", methods=["GET", "POST", "PUT", "DELETE", "PATCH", "HEAD", "OPTIONS"])
|
||||||
|
|||||||
@@ -21,6 +21,7 @@
|
|||||||
data-name="{{ u.name }}"
|
data-name="{{ u.name }}"
|
||||||
data-scope="{{ u.scope }}"
|
data-scope="{{ u.scope }}"
|
||||||
data-tagline="{{ u.tagline }}"
|
data-tagline="{{ u.tagline }}"
|
||||||
|
data-supports-files="{{ 'true' if u.supports_files else 'false' }}"
|
||||||
style="--item-accent: var({{ u.accent_token }});"
|
style="--item-accent: var({{ u.accent_token }});"
|
||||||
>
|
>
|
||||||
<div class="hub-universe-avatar">
|
<div class="hub-universe-avatar">
|
||||||
@@ -60,7 +61,20 @@
|
|||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div class="hub-topbar-right">
|
<div class="hub-topbar-right">
|
||||||
<span style="font-size: 0.75rem; color: var(--hub-text-muted);">Session sécurisée VPS ↔ NAS</span>
|
<!-- Sélecteur Toggle Mode DSH (Claude Design - Univers Nabil) -->
|
||||||
|
<div id="nabil-mode-toggle" role="tablist" aria-label="Mode du canvas" class="hub-mode-toggle">
|
||||||
|
<button id="tab-session" role="tab" aria-selected="true" class="hub-mode-tab active" type="button">
|
||||||
|
<svg width="15" height="15" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2.2" stroke-linecap="square"><path d="M21 15a2 2 0 0 1-2 2H7l-4 4V5a2 2 0 0 1 2-2h14a2 2 0 0 1 2 2z"></path></svg>
|
||||||
|
<span>Session</span>
|
||||||
|
</button>
|
||||||
|
<div class="hub-mode-divider"></div>
|
||||||
|
<button id="tab-files" role="tab" aria-selected="false" class="hub-mode-tab" type="button">
|
||||||
|
<svg width="15" height="15" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2.2" stroke-linecap="square"><path d="M4 20h14a2 2 0 0 0 2-2V9H12L10 6H4a1 1 0 0 0-1 1v12a1 1 0 0 0 1 1z"></path></svg>
|
||||||
|
<span>Explorateur DSH</span>
|
||||||
|
</button>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<span id="hub-security-badge" style="font-size: 0.75rem; color: var(--hub-text-muted);">Session sécurisée VPS ↔ NAS</span>
|
||||||
</div>
|
</div>
|
||||||
</header>
|
</header>
|
||||||
|
|
||||||
|
|||||||
+32
-1
@@ -7,7 +7,7 @@ services:
|
|||||||
restart: unless-stopped
|
restart: unless-stopped
|
||||||
user: "1026:100"
|
user: "1026:100"
|
||||||
ports:
|
ports:
|
||||||
# Bind strictement sur loopback pour n'etre accessible QUE par Cloudflare Tunnel / Tailscale
|
# Bind strictement sur loopback pour n'etre accessible QUE par Cloudflare Tunnel
|
||||||
- "127.0.0.1:8080:8080"
|
- "127.0.0.1:8080:8080"
|
||||||
volumes:
|
volumes:
|
||||||
- ./data:/app/data
|
- ./data:/app/data
|
||||||
@@ -21,8 +21,39 @@ services:
|
|||||||
- HERMES_NYORA_URL=http://100.86.197.88:3020
|
- HERMES_NYORA_URL=http://100.86.197.88:3020
|
||||||
- HERMES_PERSO_URL=http://100.86.197.88:3031
|
- HERMES_PERSO_URL=http://100.86.197.88:3031
|
||||||
- HERMES_NABIL_URL=http://127.0.0.1:8642
|
- HERMES_NABIL_URL=http://127.0.0.1:8642
|
||||||
|
- DSH_FILEBROWSER_URL=http://dsh-filebrowser:80
|
||||||
|
depends_on:
|
||||||
|
- dsh-filebrowser
|
||||||
dns:
|
dns:
|
||||||
- 1.1.1.1
|
- 1.1.1.1
|
||||||
- 8.8.8.8
|
- 8.8.8.8
|
||||||
|
networks:
|
||||||
|
- hub-net
|
||||||
labels:
|
labels:
|
||||||
com.centurylinklabs.watchtower.enable: "false"
|
com.centurylinklabs.watchtower.enable: "false"
|
||||||
|
|
||||||
|
dsh-filebrowser:
|
||||||
|
image: filebrowser/filebrowser:v2.32.0
|
||||||
|
container_name: dsh-filebrowser
|
||||||
|
restart: unless-stopped
|
||||||
|
user: "${DSH_UID:-1001}:${DSH_GID:-1001}"
|
||||||
|
command:
|
||||||
|
- "--noauth"
|
||||||
|
- "--root=/srv"
|
||||||
|
- "--baseurl=/u/nabil/files"
|
||||||
|
- "--address=0.0.0.0"
|
||||||
|
- "--port=80"
|
||||||
|
- "--branding.theme=dark"
|
||||||
|
volumes:
|
||||||
|
- /home/dsh-agent/dsh-vps/workspace:/srv
|
||||||
|
ports:
|
||||||
|
# Bind strictement loopback
|
||||||
|
- "127.0.0.1:8901:80"
|
||||||
|
networks:
|
||||||
|
- hub-net
|
||||||
|
labels:
|
||||||
|
com.centurylinklabs.watchtower.enable: "false"
|
||||||
|
|
||||||
|
networks:
|
||||||
|
hub-net:
|
||||||
|
driver: bridge
|
||||||
|
|||||||
@@ -443,3 +443,70 @@ html, body {
|
|||||||
background-color: var(--hub-bg-card-hover);
|
background-color: var(--hub-bg-card-hover);
|
||||||
color: var(--hub-text-primary);
|
color: var(--hub-text-primary);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* Mode Toggle Selector (Claude Design) */
|
||||||
|
.hub-mode-toggle {
|
||||||
|
display: none;
|
||||||
|
align-items: center;
|
||||||
|
border: 1px solid var(--hub-border-medium);
|
||||||
|
height: 36px;
|
||||||
|
border-radius: var(--hub-radius-md);
|
||||||
|
overflow: hidden;
|
||||||
|
background-color: var(--hub-bg-card);
|
||||||
|
}
|
||||||
|
|
||||||
|
.hub-mode-toggle.visible {
|
||||||
|
display: flex;
|
||||||
|
}
|
||||||
|
|
||||||
|
.hub-mode-tab {
|
||||||
|
display: flex;
|
||||||
|
align-items: center;
|
||||||
|
gap: 0.5rem;
|
||||||
|
height: 100%;
|
||||||
|
padding: 0 0.85rem;
|
||||||
|
border: none;
|
||||||
|
background: transparent;
|
||||||
|
color: var(--hub-text-secondary);
|
||||||
|
font-family: var(--hub-font-sans);
|
||||||
|
font-size: 0.8125rem;
|
||||||
|
font-weight: 700;
|
||||||
|
letter-spacing: 0.02em;
|
||||||
|
cursor: pointer;
|
||||||
|
transition: all 120ms ease;
|
||||||
|
user-select: none;
|
||||||
|
}
|
||||||
|
|
||||||
|
.hub-mode-tab:hover {
|
||||||
|
background-color: var(--hub-bg-card-hover);
|
||||||
|
color: var(--hub-text-primary);
|
||||||
|
}
|
||||||
|
|
||||||
|
.hub-mode-tab.active {
|
||||||
|
background: var(--hub-accent-current);
|
||||||
|
color: #ffffff;
|
||||||
|
cursor: default;
|
||||||
|
box-shadow: 0 0 10px var(--hub-accent-glow-current);
|
||||||
|
}
|
||||||
|
|
||||||
|
.hub-mode-divider {
|
||||||
|
width: 1px;
|
||||||
|
height: 60%;
|
||||||
|
background-color: var(--hub-border-medium);
|
||||||
|
flex: none;
|
||||||
|
}
|
||||||
|
|
||||||
|
@keyframes panelIn {
|
||||||
|
from {
|
||||||
|
opacity: 0;
|
||||||
|
transform: translateY(4px);
|
||||||
|
}
|
||||||
|
to {
|
||||||
|
opacity: 1;
|
||||||
|
transform: none;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
.hub-canvas-anim {
|
||||||
|
animation: panelIn 140ms ease both;
|
||||||
|
}
|
||||||
|
|||||||
+64
-8
@@ -1,15 +1,21 @@
|
|||||||
/**
|
/**
|
||||||
* Hermes Hub — Client-side Workspace Switcher & Context Manager
|
* Hermes Hub — Client-side Workspace Switcher & Context Manager
|
||||||
* Garantit l'isolation stricte du state front-end entre univers
|
* Garantit l'isolation stricte du state front-end entre univers
|
||||||
|
* Intègre le sélecteur toggle DSH (Session vs Explorateur de fichiers)
|
||||||
*/
|
*/
|
||||||
|
|
||||||
(function () {
|
(function () {
|
||||||
let activeUniverse = "tt";
|
let activeUniverse = "tt";
|
||||||
|
let activeMode = "session"; // "session" ou "files" (pour l'univers nabil)
|
||||||
|
|
||||||
const iframe = document.getElementById("workspace-iframe");
|
const iframe = document.getElementById("workspace-iframe");
|
||||||
const loader = document.getElementById("hub-loader");
|
const loader = document.getElementById("hub-loader");
|
||||||
const activeTitle = document.getElementById("active-universe-name");
|
const activeTitle = document.getElementById("active-universe-name");
|
||||||
const activeScope = document.getElementById("active-universe-scope");
|
const activeScope = document.getElementById("active-universe-scope");
|
||||||
const activeTagline = document.getElementById("active-universe-tagline");
|
const activeTagline = document.getElementById("active-universe-tagline");
|
||||||
|
const nabilModeToggle = document.getElementById("nabil-mode-toggle");
|
||||||
|
const tabSession = document.getElementById("tab-session");
|
||||||
|
const tabFiles = document.getElementById("tab-files");
|
||||||
|
|
||||||
// Accent mappings
|
// Accent mappings
|
||||||
const ACCENT_MAP = {
|
const ACCENT_MAP = {
|
||||||
@@ -33,21 +39,51 @@
|
|||||||
document.documentElement.style.setProperty("--hub-accent-glow-current", glow);
|
document.documentElement.style.setProperty("--hub-accent-glow-current", glow);
|
||||||
}
|
}
|
||||||
|
|
||||||
function switchUniverse(universeId) {
|
function getTargetUrl(universeId, mode) {
|
||||||
if (!universeId || (activeUniverse === universeId && iframe.src !== "about:blank")) {
|
if (universeId === "nabil" && mode === "files") {
|
||||||
return;
|
return "/u/nabil/files/";
|
||||||
}
|
}
|
||||||
|
return `/u/${universeId}/`;
|
||||||
|
}
|
||||||
|
|
||||||
|
function setMode(mode) {
|
||||||
|
activeMode = mode;
|
||||||
|
if (tabSession && tabFiles) {
|
||||||
|
if (mode === "session") {
|
||||||
|
tabSession.classList.add("active");
|
||||||
|
tabSession.setAttribute("aria-selected", "true");
|
||||||
|
tabFiles.classList.remove("active");
|
||||||
|
tabFiles.setAttribute("aria-selected", "false");
|
||||||
|
} else {
|
||||||
|
tabFiles.classList.add("active");
|
||||||
|
tabFiles.setAttribute("aria-selected", "true");
|
||||||
|
tabSession.classList.remove("active");
|
||||||
|
tabSession.setAttribute("aria-selected", "false");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Recharger le canvas avec le mode choisi
|
||||||
|
loader.classList.remove("hidden");
|
||||||
|
iframe.src = "about:blank";
|
||||||
|
setTimeout(() => {
|
||||||
|
iframe.src = getTargetUrl(activeUniverse, activeMode);
|
||||||
|
}, 50);
|
||||||
|
}
|
||||||
|
|
||||||
|
function switchUniverse(universeId) {
|
||||||
|
if (!universeId) return;
|
||||||
|
|
||||||
const btn = document.querySelector(`.hub-universe-btn[data-universe="${universeId}"]`);
|
const btn = document.querySelector(`.hub-universe-btn[data-universe="${universeId}"]`);
|
||||||
if (!btn) return;
|
if (!btn) return;
|
||||||
|
|
||||||
// 1. ISOLATION TOTALE DU STATE CLIENT
|
// 1. ISOLATION TOTALE DU STATE CLIENT
|
||||||
// Forcer le déchargement de l'iframe précédente pour éliminer tout résidu JS en mémoire
|
// Décharger immédiatement l'iframe précédente pour purger la mémoire JS
|
||||||
loader.classList.remove("hidden");
|
loader.classList.remove("hidden");
|
||||||
iframe.src = "about:blank";
|
iframe.src = "about:blank";
|
||||||
|
|
||||||
// 2. Mettre à jour l'univers actif
|
// 2. Mettre à jour l'univers actif
|
||||||
activeUniverse = universeId;
|
activeUniverse = universeId;
|
||||||
|
activeMode = "session"; // Réinitialiser le mode à session par défaut
|
||||||
|
|
||||||
// 3. Mettre à jour la classe active sur la sidebar
|
// 3. Mettre à jour la classe active sur la sidebar
|
||||||
document.querySelectorAll(".hub-universe-btn").forEach((el) => el.classList.remove("active"));
|
document.querySelectorAll(".hub-universe-btn").forEach((el) => el.classList.remove("active"));
|
||||||
@@ -60,15 +96,31 @@
|
|||||||
const name = btn.dataset.name || universeId.toUpperCase();
|
const name = btn.dataset.name || universeId.toUpperCase();
|
||||||
const scope = btn.dataset.scope || universeId;
|
const scope = btn.dataset.scope || universeId;
|
||||||
const tagline = btn.dataset.tagline || "";
|
const tagline = btn.dataset.tagline || "";
|
||||||
|
const supportsFiles = btn.dataset.supportsFiles === "true";
|
||||||
|
|
||||||
if (activeTitle) activeTitle.textContent = name;
|
if (activeTitle) activeTitle.textContent = name;
|
||||||
if (activeScope) activeScope.textContent = `Scope: ${scope}`;
|
if (activeScope) activeScope.textContent = `Scope: ${scope}`;
|
||||||
if (activeTagline) activeTagline.textContent = tagline;
|
if (activeTagline) activeTagline.textContent = tagline;
|
||||||
|
|
||||||
// 6. Charger le nouvel univers via le proxy dédié
|
// 6. Afficher ou masquer le sélecteur toggle DSH (Claude Design)
|
||||||
const targetProxyUrl = `/u/${universeId}/`;
|
if (nabilModeToggle) {
|
||||||
|
if (supportsFiles) {
|
||||||
|
nabilModeToggle.classList.add("visible");
|
||||||
|
// Reset tabs visual state
|
||||||
|
if (tabSession && tabFiles) {
|
||||||
|
tabSession.classList.add("active");
|
||||||
|
tabSession.setAttribute("aria-selected", "true");
|
||||||
|
tabFiles.classList.remove("active");
|
||||||
|
tabFiles.setAttribute("aria-selected", "false");
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
nabilModeToggle.classList.remove("visible");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// 7. Charger le nouvel univers via le proxy dédié
|
||||||
setTimeout(() => {
|
setTimeout(() => {
|
||||||
iframe.src = targetProxyUrl;
|
iframe.src = getTargetUrl(activeUniverse, activeMode);
|
||||||
}, 50);
|
}, 50);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -105,7 +157,7 @@
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Modal Personnalité
|
// Modales Personnalité & Clonage
|
||||||
const personaModal = document.getElementById("persona-modal");
|
const personaModal = document.getElementById("persona-modal");
|
||||||
const cloneModal = document.getElementById("clone-modal");
|
const cloneModal = document.getElementById("clone-modal");
|
||||||
|
|
||||||
@@ -190,6 +242,10 @@
|
|||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
|
// Toggle Mode DSH (Session vs Files)
|
||||||
|
tabSession?.addEventListener("click", () => setMode("session"));
|
||||||
|
tabFiles?.addEventListener("click", () => setMode("files"));
|
||||||
|
|
||||||
// Outils Footer
|
// Outils Footer
|
||||||
document.getElementById("btn-edit-persona")?.addEventListener("click", openPersonaModal);
|
document.getElementById("btn-edit-persona")?.addEventListener("click", openPersonaModal);
|
||||||
document.getElementById("btn-clone-universe")?.addEventListener("click", openCloneModal);
|
document.getElementById("btn-clone-universe")?.addEventListener("click", openCloneModal);
|
||||||
|
|||||||
Reference in New Issue
Block a user