2 * Canvas Desktop Viewer - Direct MeshCentral integration
3 * This component replaces the old RDS viewer with a cleaner MeshCentral connection
4 * Can be used standalone (with URL params) or embedded (with props)
7import React from 'react';
8import { useParams } from 'react-router-dom';
9import MainLayout from '../components/Layout/MainLayout';
10import { useCanvasDesktop } from '../hooks/useCanvasDesktop';
12export default function CanvasDesktopViewer({ nodeId: propNodeId, embedded = false }) {
13 const { nodeId: urlNodeId } = useParams();
14 const nodeId = propNodeId || urlNodeId; // Use prop if provided, otherwise use URL param
25 } = useCanvasDesktop(nodeId);
27 const getStatusColor = () => {
29 case 'connected': return 'text-green-600';
30 case 'connecting': return 'text-yellow-600';
31 case 'error': return 'text-red-600';
32 default: return 'text-gray-600';
36 const getStatusIcon = () => {
38 case 'connected': return '✅';
39 case 'connecting': return '🔄';
40 case 'error': return '❌';
46 <div className={embedded ? "h-full" : "p-6"}>
47 <div className="bg-white rounded-lg shadow-lg h-full flex flex-col">
49 <div className="border-b border-gray-200 px-6 py-4">
50 <div className="flex items-center justify-between">
52 <h1 className={embedded ? "text-xl font-bold text-gray-900" : "text-2xl font-bold text-gray-900"}>
53 Remote Desktop - Canvas View
55 <p className="text-sm text-gray-500 mt-1">
56 Node ID: {nodeId || 'Unknown'}
59 <div className="flex items-center gap-4">
60 {/* Status indicator */}
61 <div className="flex items-center gap-2">
62 <span className="text-2xl">{getStatusIcon()}</span>
63 <span className={`font-semibold ${getStatusColor()}`}>
64 {status.charAt(0).toUpperCase() + status.slice(1)}
71 disabled={status !== 'connected'}
72 className="px-4 py-2 bg-blue-600 text-white rounded hover:bg-blue-700 disabled:opacity-50 disabled:cursor-not-allowed"
79 className="px-4 py-2 bg-red-600 text-white rounded hover:bg-red-700"
89 <div className="mx-6 mt-4 p-4 bg-red-50 border border-red-200 rounded-lg">
90 <div className="flex items-start">
91 <span className="text-red-600 text-xl mr-3">⚠️</span>
93 <h3 className="text-red-800 font-semibold">Connection Error</h3>
94 <p className="text-red-700 text-sm mt-1">{error}</p>
101 <div className="mx-6 mt-4 p-4 bg-blue-50 border border-blue-200 rounded-lg">
102 <div className="grid grid-cols-3 gap-4 text-sm">
104 <span className="font-semibold">Phase:</span>
105 <span className="ml-2">{phase || 1}</span>
108 <span className="font-semibold">Capabilities:</span>
109 <span className="ml-2">
110 {capabilities.length > 0 ? capabilities.join(', ') : 'None'}
114 <span className="font-semibold">Protocol:</span>
115 <span className="ml-2">MeshCentral WebSocket</span>
120 {/* Canvas container */}
121 <div className="p-6 flex-1">
122 <div className="bg-gray-900 rounded-lg overflow-hidden h-full" style={{ minHeight: '600px' }}>
123 {status === 'connected' ? (
128 className="w-full h-auto cursor-pointer"
129 onMouseDown={sendMouseEvent}
130 onMouseUp={sendMouseEvent}
131 onMouseMove={sendMouseEvent}
132 onKeyDown={sendKeyEvent}
133 onKeyUp={sendKeyEvent}
135 style={{ imageRendering: 'auto' }}
138 <div className="flex items-center justify-center h-full min-h-[600px]">
139 <div className="text-center">
140 {status === 'connecting' && (
142 <div className="animate-spin text-6xl mb-4">🔄</div>
143 <p className="text-white text-lg">Connecting to remote desktop...</p>
146 {status === 'disconnected' && (
148 <div className="text-6xl mb-4">⚪</div>
149 <p className="text-white text-lg">Not connected</p>
152 {status === 'error' && (
154 <div className="text-6xl mb-4">❌</div>
155 <p className="text-white text-lg">Connection failed</p>
156 <p className="text-gray-400 text-sm mt-2">{error}</p>
166 <div className="border-t border-gray-200 px-6 py-4 bg-gray-50">
167 <div className="text-sm text-gray-600">
170 <strong>Phase 1:</strong> Authentication and ping/pong testing.
171 Screen streaming coming in Phase 2.
176 <strong>Phase 2:</strong> Screen streaming active.
177 Mouse and keyboard input functional.
182 <strong>Phase 3:</strong> Quality controls, compression, clipboard sync, and file transfer.
187 <strong>Phase 4:</strong> Production-ready with full optimization and polish.
196 return embedded ? content : <MainLayout>{content}</MainLayout>;