mirror of
https://github.com/Termix-SSH/Termix.git
synced 2026-08-29 18:31:33 +00:00
feat: collaboration rooms with switchable presenter (#1328)
* feat: add collaboration rooms with switchable presenter Rooms are a group of members watching one stage - the live SSH/RDP/VNC session the current presenter shares. Any member can take over the stage; the host can invite, force-stop and end the meeting. Stages reuse session_shares (new room share type), so gating, recording, expiry and the global sharing toggle all apply unchanged. * feat: add stage control handoff to collaboration rooms The presenter or host can grant any member write access to the live stage and take it back; members can raise a hand to ask. SSH flips the participant's permission on the live gate; RDP/VNC re-mint the viewer's join token. Control clears on every stage switch. * feat: guest links, role invites and invite awareness for collab rooms - Anonymous guest link per room (host toggles/rotates), followed by polling the public resolve endpoint; SSH guests join over the terminal WS with roomGuestToken, guac guests get read-only join tokens - Invite by role (expands to current members, snapshot semantics) - Toast when a room you were invited to appears - Stale stages are cleared lazily when the presenter is gone - Telnet presenting, expired-tab fallback, documented single-instance and guac-kick limits - Tests for the collab routes, room hub, share access and control flip * fix: keep remote desktop collaboration read-only
This commit is contained in:
@@ -27,6 +27,7 @@ import {
|
||||
Plug,
|
||||
ScrollText,
|
||||
Sparkles,
|
||||
Presentation,
|
||||
Workflow,
|
||||
} from "lucide-react";
|
||||
import { lazy, Suspense } from "react";
|
||||
@@ -57,6 +58,11 @@ const loadTerminalFeature = () =>
|
||||
default: m.Terminal,
|
||||
}));
|
||||
const TerminalFeature = lazy(loadTerminalFeature);
|
||||
const CollabRoomTab = lazy(() =>
|
||||
import("@/features/collab/CollabRoomTab").then((m) => ({
|
||||
default: m.CollabRoomTab,
|
||||
})),
|
||||
);
|
||||
const LocalTerminal = lazy(() =>
|
||||
import("@/features/local-terminal/LocalTerminal").then((m) => ({
|
||||
default: m.LocalTerminal,
|
||||
@@ -318,6 +324,8 @@ export function tabIcon(type: TabType) {
|
||||
return <LayoutGrid className="size-3.5" />;
|
||||
case "fleet-inventory":
|
||||
return <Boxes className="size-3.5" />;
|
||||
case "collab":
|
||||
return <Presentation className="size-3.5" />;
|
||||
case "termix-id":
|
||||
return <Fingerprint className="size-3.5" />;
|
||||
case "alerts":
|
||||
@@ -615,6 +623,11 @@ export function renderTabContent(
|
||||
<FleetInventoryTab fleetId={tab.fleetId} isVisible={isVisible} />,
|
||||
);
|
||||
|
||||
case "collab":
|
||||
return withTabSuspense(
|
||||
<CollabRoomTab roomId={tab.collabRoomId} isVisible={isVisible} />,
|
||||
);
|
||||
|
||||
case "termix-id":
|
||||
return withTabSuspense(
|
||||
<PanelTabFrame>
|
||||
|
||||
Reference in New Issue
Block a user