feat: convert tmux monitoring into a plugin (B10)

This commit is contained in:
LukeGus committed 2026-09-23 22:42:56 -05:00
1 parent 79d77678c9
commit 708eedb861
145 files changed
+30308 -4458

No files matched your search

-30
View File
@@ -25,7 +25,6 @@ import {
import {
Globe,
Info,
Layers, // --- tmux-monitor ---
Palette,
Pencil,
Plus,
@@ -2062,35 +2061,6 @@ export function HostEditor({
</div>
</div>
</SectionCard>
{/* --- tmux-monitor --- */}
<SectionCard
title={t("tmuxMonitor.title")}
icon={<Layers className="size-3.5" />}
>
<div className="flex flex-col gap-4 py-3">
<SettingRow
label={t("hosts.enableTmuxMonitor")}
description={
<>
{t("hosts.enableTmuxMonitorDesc")}{" "}
<a
href="https://docs.termix.site/features/terminal/tmux"
target="_blank"
rel="noreferrer"
className="text-accent-brand hover:underline"
>
{t("hosts.docsLink")}
</a>
</>
}
>
<FakeSwitch
checked={form.enableTmuxMonitor}
onChange={(v) => setField("enableTmuxMonitor", v)}
/>
</SettingRow>
</div>
</SectionCard>
</>
)}
+5 -63
View File
@@ -11,7 +11,6 @@ import {
GripVertical,
Key,
KeyRound,
Layers, // --- tmux-monitor ---
Link,
MemoryStick,
MoreHorizontal,
@@ -113,33 +112,6 @@ export function buildStatusTooltip(
return `${protocols.join(", ")}: ${statusLabel}`;
}
/**
* Core's own per-host tools. Ways to connect and plugin tools (terminal,
* remote desktop, Docker, metrics) are host actions plugins register.
*/
export function getSshActions(host: Host): {
type: TabType;
icon: typeof Terminal;
label: string;
order: number;
}[] {
return [
// --- tmux-monitor --- opt-in per host, off by default
host.enableSsh &&
host.enableTmuxMonitor && {
type: "tmux_monitor" as TabType,
icon: Layers,
label: "Tmux Monitor",
order: 70,
},
].filter(Boolean) as {
type: TabType;
icon: typeof Terminal;
label: string;
order: number;
}[];
}
/** Plugin actions sort by order; connect actions default to the end. */
function actionOrder(action: HostActionDef): number {
return action.order ?? (action.kind === "connect" ? 100 : 50);
@@ -411,13 +383,9 @@ export function HostItem({
const trayButtonClass =
"flex items-center justify-center size-[22.75px] text-muted-foreground/60 hover:text-foreground hover:bg-muted transition-colors";
const sshActions = getSshActions(host);
const availableActions: TabType[] = [
...sshActions.map(({ type }) => type),
...pluginActions.flatMap((action) =>
action.tabType ? [action.tabType] : [],
),
];
const availableActions: TabType[] = pluginActions.flatMap((action) =>
action.tabType ? [action.tabType] : [],
);
// Empty when no running plugin can connect to this host.
const defaultAction: TabType =
defaultConnectAction(allHostActions, host)?.tabType ?? "";
@@ -450,19 +418,8 @@ export function HostItem({
else if (action.tabType) openHostTab(action.tabType);
};
/** Core tools and plugin actions in one row, in order. */
/** Plugin actions in row order. */
const rowEntries = [
...sshActions.map((action) => ({
key: action.type,
order: action.order,
icon: action.icon,
label: action.label,
tabType: action.type as string | undefined,
tray: true,
items: undefined as
{ id: string; label: string; run: () => void }[] | undefined,
run: () => openHostTab(action.type),
})),
...pluginActions.map((action) => {
const items = action.items?.(host);
return {
@@ -799,20 +756,6 @@ export function HostItem({
{t("hosts.copyLink")}
</DropdownMenuSubTrigger>
<DropdownMenuSubContent>
{host.enableSsh && host.enableTmuxMonitor && (
<DropdownMenuItem
onClick={(e) => {
e.stopPropagation();
writeClipboardText(
`${window.location.origin}?view=tmux_monitor&hostId=${host.id}`,
);
toast.success(t("hosts.tmuxMonitorUrlCopied"));
}}
>
<Layers className="size-3.5 mr-2" />
{t("hosts.copyTmuxMonitorUrlAction")}
</DropdownMenuItem>
)}
{pluginActions
.filter((action) => action.copyUrlView)
.map((action) => {
@@ -1015,13 +958,12 @@ export function HostItem({
// reachable. If the host only exposes a single action, just launch it.
if (isTouchOnly) {
e.stopPropagation();
const actionCount = getSshActions(host).length;
const otherProtocols = [
host.enableRdp,
host.enableVnc,
host.enableTelnet,
].filter(Boolean).length;
if (actionCount + otherProtocols <= 1) {
if (otherProtocols <= 1) {
openHostTab(defaultAction);
} else {
onTrayOpenChange?.(!isTrayOpen);