Skip to content

Commit

Permalink
Cleaned up interface and added back auto refresh
Browse files Browse the repository at this point in the history
  • Loading branch information
PixNyb committed Jul 29, 2024
1 parent c715914 commit 31bd5fb
Show file tree
Hide file tree
Showing 8 changed files with 80 additions and 34 deletions.
1 change: 1 addition & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -37,3 +37,4 @@ next-env.d.ts

docker-compose.y*ml
Dockerfile.*
*.sh
10 changes: 4 additions & 6 deletions app.js
Original file line number Diff line number Diff line change
Expand Up @@ -34,12 +34,12 @@ nextApp.prepare().then(() => {
server.on("upgrade", (req, socket, head) => {
const { pathname } = parse(req.url || "/", true);

if (pathname === "/_next/webpack-hmr") {
if (pathname === "/_next/webpack-hmr")
nextApp.getUpgradeHandler()(req, socket, head);
}

if (pathname === "/api/socket") {
ws.handleUpgrade(req, socket, head, (socket) => {
console.debug('Client connected to WebSocket server');
const params = new URLSearchParams(req.url.split('?')[1]);
const host = params.get('host');
const port = params.get('port');
Expand All @@ -53,8 +53,6 @@ nextApp.prepare().then(() => {
const vncSocket = new net.Socket();

vncSocket.connect(port, host, () => {
console.log(`Connected to VNC server at ${host}:${port}`);

socket.on('message', (data) => {
try {
vncSocket.write(data);
Expand All @@ -72,13 +70,13 @@ nextApp.prepare().then(() => {
});

socket.on('close', () => {
console.log('Client disconnected from WebSocket server');
console.debug('Client disconnected from WebSocket server');
vncSocket.end();
});
});

vncSocket.on('close', () => {
console.log('Disconnected from VNC server');
console.debug('Disconnected from VNC server');
socket.close();
});
});
Expand Down
2 changes: 1 addition & 1 deletion pages/api/containers.js
Original file line number Diff line number Diff line change
Expand Up @@ -102,7 +102,7 @@ export default async function handler(req, res) {
image: container.Image,
status: container.Status,
labels: container.Labels,
network: container.NetworkSettings,
network: container.NetworkSettings.Networks[sharedNetwork],
host: vncViewerIp,
port: vncViewerPort,
};
Expand Down
14 changes: 4 additions & 10 deletions pages/view/[id].js
Original file line number Diff line number Diff line change
@@ -1,6 +1,5 @@
import VncViewer from '@/app/components/VncViewer';
import Head from 'next/head';
import Link from 'next/link';

export async function getServerSideProps(context) {
const { id } = context.params;
Expand All @@ -19,15 +18,10 @@ export async function getServerSideProps(context) {
export default function Page({ container }) {
return (
<>
<div style={{ display: 'flex', flexDirection: 'row', justifyContent: 'center', alignItems: 'center', width: '100%', gap: '1rem', padding: '2rem 2rem 1rem 2rem' }}>
<Link href='/'>
<i className='fas fa-arrow-left'></i>
</Link>
<h1 style={{ margin: 0 }}>
{container.name}
</h1>
</div>
<VncViewer host={container.host} port={container.port} />
<VncViewer title={container.name} host={container.host} port={container.port} link={{
path: '/',
icon: 'fas fa-arrow-left',
}} />
</>
)
}
Expand Down
6 changes: 2 additions & 4 deletions src/app/components/ContainerCard.js
Original file line number Diff line number Diff line change
Expand Up @@ -16,11 +16,9 @@ export default function ContainerCard({ container }) {

return (
<div className="card">
<VncViewer host={containerData.host} port={containerData.port} options={{
expandPath: `/view/${containerData.id}`
<VncViewer title={containerData.name} host={containerData.host} port={containerData.port} link={{
path: `/view/${containerData.id}`
}} />
<h3>{containerData.name}</h3>
<span className="text-small status">{container.image}</span>
</div>
);
}
54 changes: 47 additions & 7 deletions src/app/components/ContainerList.js
Original file line number Diff line number Diff line change
@@ -1,33 +1,73 @@
'use client';

import { useEffect, useState } from "react";
import { useEffect, useRef, useState } from "react";
import ContainerCard from "./ContainerCard";

export default function ContainerList() {
const [containers, setContainers] = useState([]);
const containerMapRef = useRef(new Map());

useEffect(() => {
async function fetchContainers() {
try {
const response = await fetch("/api/containers");
const data = await response.json();
setContainers(data);

const newContainerMap = new Map();
data.forEach(container => {
newContainerMap.set(container.id, container);
});

// Check if there are any changes
let hasChanges = false;
if (newContainerMap.size !== containerMapRef.current.size) {
hasChanges = true;
} else {
for (let [id, container] of newContainerMap) {
if (!containerMapRef.current.has(id) || JSON.stringify(containerMapRef.current.get(id)) !== JSON.stringify(container)) {
hasChanges = true;
break;
}
}
}

if (hasChanges) {
containerMapRef.current = newContainerMap;
setContainers(Array.from(newContainerMap.values()));
}
} catch (error) {
console.error(error);
}
}

fetchContainers();

// const interval = setInterval(fetchContainers, 5000);
// return () => clearInterval(interval);
const interval = setInterval(fetchContainers, 5000);
return () => clearInterval(interval);
}, []);

return (
<div className="card-holder">
{containers.map((container) => (
<ContainerCard key={container.id} container={container} />
))}
{containers.length != 0 &&
containers.map((container) => (
<ContainerCard key={container.id} container={container} />
))
}

{containers.length === 0 &&
<div>
<p>
To get started, add the label <code>vnc-viewer.enabled</code> to your container running a VNC server and make sure it exists in the same network as the vnc-viewer container.<br />
Optionally, you can specify a custom label and port using <code>vnc-viewer.label</code> and <code>vnc-viewer.port</code>.
</p>
<pre>
<code>docker run -d --label vnc-viewer.enabled my-container</code>
</pre>
<p>
Read the <a href="https://github.com/PixNyb/vnc-viewer/blob/main/README.md">documentation</a> for more information.
</p>
</div>
}
</div>
);
}
13 changes: 11 additions & 2 deletions src/app/components/VncViewer.css
Original file line number Diff line number Diff line change
Expand Up @@ -45,7 +45,8 @@
}

.vnc-canvas .status,
.vnc-canvas .expand {
.vnc-canvas .expand,
.vnc-canvas .title {
position: absolute;
bottom: 0;
right: 0;
Expand All @@ -59,10 +60,18 @@
}

.vnc-canvas .expand {
bottom: unset;
top: 0;
}

.vnc-canvas .title {
bottom: unset;
right: unset;
width: unset;
top: 0;
right: 0;
left: 0;
padding: 0 0.5rem;
font-weight: 500;
}

.vnc-canvas .login {
Expand Down
14 changes: 10 additions & 4 deletions src/app/components/VncViewer.js
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@ import Link from 'next/link';
import { useEffect, useRef, useState } from 'react';
import './VncViewer.css';

const VncViewer = ({ host, port, options }) => {
const VncViewer = ({ host, port, options, link, title }) => {
const canvasRef = useRef(null);
const rfbRef = useRef(null);
const [RFB, setRFB] = useState(null);
Expand Down Expand Up @@ -126,12 +126,18 @@ const VncViewer = ({ host, port, options }) => {
className={`vnc-canvas ${isConnected ? 'connected' : requiresAuthentication ? 'requires-authentication' : 'disconnected'}`}
>
<div className='overlay'>
{isConnected && options?.expandPath &&
{title &&
<div className='title'>
{title}
</div>
}

{isConnected && link &&
<div className='expand'>
<Link href={{
pathname: options.expandPath,
pathname: link.path,
}}>
<i className='fas fa-expand'></i>
<i className={link.icon || 'fas fa-expand'}></i>
</Link>
</div>
}
Expand Down

0 comments on commit 31bd5fb

Please sign in to comment.