- useRdp.ts: JsonWsTunnel class extends Guacamole.Tunnel to bridge guacamole-common-js (expects raw protocol) with our JSON gateway (consistent with SSH/SFTP message envelope pattern). Parses length-prefixed Guacamole instructions, dispatches to Guacamole.Client. Handles mouse/keyboard input, clipboard send, and session lifecycle. - RdpCanvas.vue: full-size container that mounts the Guacamole display canvas. Calls useRdp().connectRdp() on mount, cleans up on unmount. Exposes sendClipboard() and disconnect() for toolbar integration. - RdpToolbar.vue: auto-hiding floating toolbar (3s idle timeout) with clipboard paste dialog, fullscreen toggle (HTML5 Fullscreen API), settings panel stub, and disconnect button. - SessionContainer.vue: renders RdpCanvas + RdpToolbar when session.protocol === 'rdp', replacing the Phase 3 placeholder. Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
67 lines
1.5 KiB
Vue
67 lines
1.5 KiB
Vue
<script setup lang="ts">
|
|
import { ref, onMounted, onBeforeUnmount } from 'vue'
|
|
import { useRdp } from '~/composables/useRdp'
|
|
|
|
const props = defineProps<{
|
|
hostId: number
|
|
hostName: string
|
|
color?: string | null
|
|
}>()
|
|
|
|
const container = ref<HTMLDivElement | null>(null)
|
|
const { connectRdp } = useRdp()
|
|
|
|
let rdpSession: ReturnType<ReturnType<typeof useRdp>['connectRdp']> | null = null
|
|
|
|
// Expose to parent (RdpToolbar uses these)
|
|
const sendClipboard = (text: string) => rdpSession?.sendClipboardText(text)
|
|
const disconnect = () => rdpSession?.disconnect()
|
|
|
|
defineExpose({ sendClipboard, disconnect })
|
|
|
|
onMounted(() => {
|
|
if (!container.value) return
|
|
|
|
rdpSession = connectRdp(
|
|
container.value,
|
|
props.hostId,
|
|
props.hostName,
|
|
props.color ?? null,
|
|
{
|
|
width: container.value.clientWidth,
|
|
height: container.value.clientHeight,
|
|
},
|
|
)
|
|
})
|
|
|
|
onBeforeUnmount(() => {
|
|
rdpSession?.disconnect()
|
|
rdpSession = null
|
|
})
|
|
</script>
|
|
|
|
<template>
|
|
<!-- Full-size container for the Guacamole display canvas.
|
|
The Guacamole client appends its own <canvas> element here. -->
|
|
<div
|
|
ref="container"
|
|
class="rdp-canvas-container"
|
|
/>
|
|
</template>
|
|
|
|
<style scoped>
|
|
.rdp-canvas-container {
|
|
@apply absolute inset-0 bg-gray-950 overflow-hidden cursor-default;
|
|
}
|
|
|
|
/* Guacamole appends a display div; make it fill the container */
|
|
.rdp-canvas-container :deep(> div) {
|
|
width: 100% !important;
|
|
height: 100% !important;
|
|
}
|
|
|
|
.rdp-canvas-container :deep(canvas) {
|
|
display: block;
|
|
}
|
|
</style>
|