Make Time Travel modal-only

Add a Time Travel entry directly under Files in the sidebar dropdown and route it through the existing modal. Stop Time Travel from registering or mounting a right-canvas surface, and keep modal refresh tied to the modal state.
This commit is contained in:
Alessandro 2026-05-02 17:20:05 +02:00
parent 9fc3ff20a4
commit ae94f158df
5 changed files with 19 additions and 47 deletions

View file

@ -1,7 +1,8 @@
export default function refreshTimeTravelOnContextChange(ctx) {
const store = globalThis.Alpine?.store?.("timeTravel");
const canvas = globalThis.Alpine?.store?.("rightCanvas");
if (!store || !canvas?.isOpen || canvas.activeSurfaceId !== "time-travel") return;
const modalOpen = globalThis.isModalOpen?.("/plugins/_time_travel/webui/main.html")
|| globalThis.isModalOpen?.("plugins/_time_travel/webui/main.html");
if (!store || !modalOpen) return;
const nextContextId = String(ctx?.snapshot?.context || "");
if (nextContextId && nextContextId !== store.contextId) {
store.scheduleRefresh({ contextId: nextContextId, reason: "context-change" });

View file

@ -1,8 +1 @@
<div
class="right-canvas-surface-panel time-travel-canvas-surface"
data-surface-id="time-travel"
x-show="$store.rightCanvas && $store.rightCanvas.isOpen && $store.rightCanvas.activeSurfaceId === 'time-travel'"
style="display: none;"
>
<x-component path="/plugins/_time_travel/webui/time-travel-panel.html" mode="canvas"></x-component>
</div>
<!-- Time Travel is modal-only; the right canvas must not mount its panel. -->

View file

@ -1,37 +1,3 @@
function waitForElement(selector, timeoutMs = 3000) {
const found = document.querySelector(selector);
if (found) return Promise.resolve(found);
return new Promise((resolve) => {
const timeout = globalThis.setTimeout(() => {
observer.disconnect();
resolve(document.querySelector(selector));
}, timeoutMs);
const observer = new MutationObserver(() => {
const element = document.querySelector(selector);
if (!element) return;
globalThis.clearTimeout(timeout);
observer.disconnect();
resolve(element);
});
observer.observe(document.body, { childList: true, subtree: true });
});
}
export default async function registerTimeTravelSurface(canvas) {
canvas.registerSurface({
id: "time-travel",
title: "Time Travel",
icon: "history",
order: 30,
modalPath: "/plugins/_time_travel/webui/main.html",
async open(payload = {}) {
await waitForElement('[data-surface-id="time-travel"] .time-travel-panel');
const store = globalThis.Alpine?.store?.("timeTravel");
await store?.onOpen?.(payload);
},
async close() {
const store = globalThis.Alpine?.store?.("timeTravel");
store?.cleanup?.();
},
});
export default async function registerTimeTravelSurface() {
// Time Travel is opened from the sidebar dropdown as a modal-only surface.
}

View file

@ -0,0 +1,12 @@
<!-- Time Travel -->
<div x-data>
<button
x-move-after="#sidebar-files-dropdown"
class="dropdown-item"
id="time-travel-dropdown"
title="Time Travel"
@click="ensureModalOpen('/plugins/_time_travel/webui/main.html'); $store.sidebar.menuClose()">
<span class="material-symbols-outlined">history</span>
<span>Time Travel</span>
</button>
</div>

View file

@ -83,7 +83,7 @@
<span>Projects</span>
</button>
<button class="dropdown-item" @click="$store.chatInput.browseFiles(); $store.sidebar.menuClose()">
<button id="sidebar-files-dropdown" class="dropdown-item" @click="$store.chatInput.browseFiles(); $store.sidebar.menuClose()">
<span class="material-symbols-outlined">folder</span>
<span>Files</span>
</button>