Fix dead Unreal plugin actions, sync toast flood, Team Relay theming

- ue bridge: Launch / Build now read live refs. They captured startBuild /
  launchUE from the render where plugins loaded — before the async .uproject
  and .sln detection had resolved — so both saw empty paths forever. hasProject
  used the live ref, so the menu items showed up and then did nothing.
- Get Latest / Sync to revision: summarise `p4 sync` stdout (syncSummary)
  instead of dumping every depot path into the toast. flash() caps length and
  .toast caps height so no raw output can blow up the bubble again.
- Team Relay: use the real theme tokens — --txt / --add / --del, not
  --text / --ok / --err, which don't exist and silently fell back to a
  near-white hardcode, invisible on the light theme. Bumped to 1.0.1.
- Plugin dock panels get a status-bar button next to Terminal / Log; the tabs
  were otherwise only reachable from the Actions menu.
- PLUGINS.md documents the theme token names.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
This commit is contained in:
Bonchellon
2026-07-18 16:50:14 +03:00
parent 20c94ef9f0
commit 37f5c504f7
7 changed files with 81 additions and 16 deletions

View File

@ -306,6 +306,35 @@ export function fmtTime(t?: string): string {
return d.toLocaleString(undefined, { day: "2-digit", month: "2-digit", year: "numeric", hour: "2-digit", minute: "2-digit" });
}
/** Condense `p4 sync` stdout into one short line.
*
* A sync prints one line per file — `//depot/F.uasset#3 - updating d:\ws\F.uasset` —
* so a real Get Latest returns thousands of full paths. Dumping that into a toast
* buries the screen; the per-file detail already streamed into the transfer dialog.
* Short outputs ("File(s) up-to-date.") pass through unchanged. */
export function syncSummary(out: string): string {
const text = (out || "").trim();
if (!text) return "up to date";
const lines = text.split("\n").map((l) => l.trim()).filter(Boolean);
// p4 says its piece in one line when nothing moved ("File(s) up-to-date.") and
// so do server errors — keep those verbatim; flash() caps the length.
if (lines.length === 1) return lines[0];
let added = 0, updated = 0, deleted = 0;
for (const l of lines) {
if (/ - (added as|refreshing) /.test(l)) added++;
else if (/ - (updating|replacing) /.test(l)) updated++;
else if (/ - deleted as /.test(l)) deleted++;
}
const moved = added + updated + deleted;
// unrecognised shape (server notices, errors) — report the line count, not the text
if (!moved) return `${lines.length.toLocaleString()} lines`;
const parts: string[] = [];
if (added) parts.push(`+${added.toLocaleString()}`);
if (updated) parts.push(`~${updated.toLocaleString()}`);
if (deleted) parts.push(`${deleted.toLocaleString()}`);
return `${moved.toLocaleString()} files (${parts.join(" ")})`;
}
// action -> single-char status + css class
export function statusOf(action?: string): { ch: string; cls: string } {
const a = (action || "").toLowerCase();