58 lines
2.3 KiB
JavaScript
58 lines
2.3 KiB
JavaScript
// 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");
|
|
}
|