// Hello Exbyte — example plugin. // A plugin is a plain ES module that exports `activate(host)`. The host is the // only way the plugin touches the app; what it can reach is gated by the // "permissions" in plugin.json. export function activate(host) { host.log("activating", host.plugin.id, "v", host.version); // 1) A menu action (appears under the Actions menu). host.ui.addMenuItem("Say hello 👋", () => { const me = host.info()?.userName || "there"; host.flash(`Hello, ${me}! (from the Hello Exbyte plugin)`); host.notify("Hello Exbyte", "The example plugin says hi."); }); // 2) A file context-menu item (right-click a file in Changes). host.ui.addFileContextItem("Copy depot path (plugin)", (file) => { if (file.depotFile) { host.clipboard.write(file.depotFile); host.flash("Copied: " + file.depotFile); } }); // 3) A view — a per-workspace notepad, persisted with host.storage. // Opens from the Actions menu (listed by its title). host.ui.addView({ id: "notes", title: "Workspace Notes", render: (el) => { const key = "notes:" + (host.info()?.clientName || "default"); const ta = document.createElement("textarea"); ta.value = host.storage.get(key) || ""; ta.placeholder = "Jot notes for this workspace… (saved locally, per workspace)"; ta.style.cssText = "width:100%;height:320px;box-sizing:border-box;resize:vertical;" + "background:var(--input-bg,#111);color:var(--txt,#eee);" + "border:1px solid var(--border,#333);border-radius:10px;padding:12px;" + "font:13px/1.6 system-ui;outline:none"; ta.addEventListener("input", () => host.storage.set(key, ta.value)); el.appendChild(ta); // optional cleanup returned to the host: return () => host.storage.set(key, ta.value); }, }); // 4) A submit guard — blocks (with a confirm) files that look like WIP. // This is the same hook point a reference-integrity guard would use. host.ui.addSubmitHook((files) => { const wip = files.filter((f) => /(^|\/)(wip|temp|scratch)[^/]*$/i.test(f.depotFile || "")); if (wip.length) { return { ok: false, message: `${wip.length} file(s) look like work-in-progress (wip / temp / scratch).` }; } return { ok: true }; }); host.log("activated"); }