import { apiGet } from "./api.js";
import { getPref, setPref } from "./prefs.js";
const VIEWS = ["xterm", "reader", "read"];
export function createViewController({
root,
session,
terminal,
createReader,
createReadMode,
}) {
const { core } = terminal;
const termEl = root.querySelector("#terminal");
const readerEl = root.querySelector("#reader");
const readModeEl = root.querySelector("#readmode");
const overlay = root.querySelector("#touchOverlay");
let current = "xterm";
let disposed = false;
const windowViews = new Map();
function activeWindowId() {
const p = core.panes[core.activeIndex];
return p?.id || null;
}
function storedDefaultView() {
const stored = getPref("default_view");
return VIEWS.includes(stored) ? stored : "xterm";
}
const reader = createReader({
host: readerEl,
document: terminal.document,
handlers: {
onCommandMenu: () => terminal.openCommandMenu(),
onSwitchWindow: (dir) => core.switchWindow(dir),
onReconnect: () => core.reconnect(),
onExit: () => {
swap("xterm");
terminal.showInputBar?.();
},
onTwoPullMove: (pull, vh) => terminal.twoPullMove(pull, vh),
onTwoPullEnd: (pull, vh) => terminal.twoPullEnd(pull, vh),
},
});
const readMode = createReadMode({
host: readModeEl,
session,
fetchPage: apiGet,
handlers: {
onExit: () => {
swap("xterm");
terminal.showInputBar?.();
},
},
});
function applyView(mode, { persist = true } = {}) {
if (!VIEWS.includes(mode)) return;
if (mode === current) {
terminal.refreshViewToggle?.();
return;
}
if (current === "reader") reader.unmount();
if (current === "read") readMode.unmount();
if (mode === "xterm") {
termEl.classList.remove("hidden");
if (
overlay &&
("ontouchstart" in window || navigator.maxTouchPoints > 0)
) {
overlay.style.pointerEvents = "auto";
}
setTimeout(() => {
if (!disposed) core.resize();
}, 0);
} else {
termEl.classList.add("hidden");
if (overlay) overlay.style.pointerEvents = "none";
if (mode === "reader") reader.mount();
else readMode.mount();
}
current = mode;
if (persist) {
setPref("default_view", mode);
if (mode !== "read") {
const wid = activeWindowId();
if (wid) windowViews.set(wid, mode);
}
}
terminal.refreshViewToggle?.();
}
function swap(mode) {
applyView(mode, { persist: true });
}
function applyStoredViewForActiveWindow() {
if (current === "read") return;
const wid = activeWindowId();
const stored = (wid && windowViews.get(wid)) || null;
applyView(stored || storedDefaultView(), { persist: false });
}
function pruneViewPrefs() {
const live = new Set(core.panes.map((p) => p.id).filter(Boolean));
for (const wid of windowViews.keys()) {
if (!live.has(wid)) windowViews.delete(wid);
}
}
const onPanes = () => {
if (disposed) return;
pruneViewPrefs();
applyStoredViewForActiveWindow();
};
core.addEventListener("panes", onPanes);
const bootView = storedDefaultView();
if (bootView !== "xterm") {
setTimeout(() => {
if (!disposed) applyView(bootView, { persist: false });
}, 0);
}
terminal.refreshViewToggle?.();
function dispose() {
if (disposed) return;
disposed = true;
core.removeEventListener("panes", onPanes);
reader.dispose();
readMode.dispose();
}
return {
swap,
get current() {
return current;
},
reader,
readMode,
dispose,
};
}