File size: 7,416 Bytes
aa886e5
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
7176fec
aa886e5
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
7176fec
aa886e5
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
<script lang="ts">
	import { Button } from "@/components/ui/button";
	import * as Dialog from "@/components/ui/dialog";
	import * as Card from "@/components/ui/card";
	import { Badge } from "@/components/ui/badge";
	import { toast } from "svelte-sonner";

	interface Props {
		workspaceId: string;
		open?: boolean;
	}

	let { workspaceId, open = $bindable(false) }: Props = $props();

	// Copy workspace ID to clipboard
	let isCopying = $state(false);
	
	const copyWorkspaceId = async () => {
		try {
			isCopying = true;
			await navigator.clipboard.writeText(workspaceId);
			toast.success('Workspace ID copied!', {
				description: 'Share this ID with others to access the same video streams, robot controls, and Inference Sessions in this workspace.'
			});
			setTimeout(() => {
				isCopying = false;
			}, 200);
		} catch (err) {
			console.error('Failed to copy workspace ID:', err);
			toast.error('Failed to copy workspace ID');
			isCopying = false;
		}
	};

	// Extract first and last 3 letters from workspace ID
	const getWorkspaceDisplay = (id: string) => {
		if (id.length <= 6) return `#${id}`;
		return `#${id.slice(0, 3)}...${id.slice(-3)}`;
	};

	// Copy full URL to clipboard
	const copyUrl = async () => {
		const url = `https://blanchon-robothub-frontend.hf.space/${workspaceId}`;
		try {
			await navigator.clipboard.writeText(url);
			toast.success('Workspace URL copied!', {
				description: 'Share this URL for direct access to this workspace.'
			});
		} catch (err) {
			console.error('Failed to copy URL:', err);
			toast.error('Failed to copy URL');
		}
	};
</script>

<!-- Workspace ID Button -->
<div class="flex items-center overflow-hidden rounded-lg h-8">
	<div class="flex items-center h-full bg-slate-100 dark:bg-slate-800 rounded-lg overflow-hidden border border-slate-200 dark:border-slate-700">
		<!-- Workspace ID Display with Copy on Hover -->
		<button
			onclick={copyWorkspaceId}
			class="group relative flex items-center px-3 h-full text-sm font-mono text-slate-700 dark:text-slate-300 bg-slate-50 dark:bg-slate-900 hover:bg-slate-100 dark:hover:bg-slate-800 transition-colors duration-200 cursor-pointer"
			title="Click to copy workspace ID"
		>
			<!-- Workspace ID Text -->
			<span class="transition-opacity duration-300 group-hover:opacity-0">
				{getWorkspaceDisplay(workspaceId)}
			</span>
			
			<!-- Copy Icon (appears on hover) -->
			<span class="absolute inset-0 flex items-center justify-center opacity-0 group-hover:opacity-100 transition-opacity duration-300">
				<span 
					class="icon-[mdi--content-copy] size-4 text-slate-600 dark:text-slate-400 transition-transform duration-200"
					class:animate-pulse={isCopying}
					class:scale-110={isCopying}
				></span>
			</span>
		</button>
		
		<!-- Modal Button -->
		<Button
			variant="ghost"
			size="sm"
			onclick={() => open = true}
			class="rounded-none border-0 border-l border-slate-200 dark:border-slate-700 px-3 h-full text-slate-600 dark:text-slate-400 hover:bg-slate-200 dark:hover:bg-slate-700 hover:text-slate-900 dark:hover:text-slate-100 hover:border-slate-300 dark:hover:border-slate-600 transition-all duration-200"
			title="Open workspace details"
		>
			<span class="icon-[mdi--information-outline] size-4"></span>
		</Button>
	</div>
</div>

<!-- Workspace Details Modal -->
<Dialog.Root bind:open>
	<Dialog.Content
		class="max-w-lg border-slate-300 bg-slate-100 text-slate-900 dark:border-slate-600 dark:bg-slate-900 dark:text-slate-100"
	>
		<Dialog.Header class="pb-4">
			<Dialog.Title class="flex items-center gap-2 text-lg font-bold text-slate-900 dark:text-slate-100">
				<span class="icon-[mdi--share-variant] size-5 text-blue-500 dark:text-blue-400"></span>
				Workspace Sharing
			</Dialog.Title>
			<Dialog.Description class="text-sm text-slate-600 dark:text-slate-400">
				Connect and collaborate with others using this workspace
			</Dialog.Description>
		</Dialog.Header>

		<div class="space-y-4">
			<!-- Workspace URL -->
			<Card.Root class="gap-2 border-blue-300/30 bg-blue-100/10 dark:border-blue-500/30 dark:bg-blue-500/10">
				<Card.Header >
					<Card.Title class="flex items-center gap-2 text-sm text-blue-700 dark:text-blue-200">
						<span class="icon-[mdi--link] size-4"></span>
						Direct Access URL
					</Card.Title>
				</Card.Header>
				<Card.Content class="pt-0">
					<div class="space-y-2">
						<div class="rounded-lg border border-slate-300 bg-slate-50 p-2 dark:border-slate-600 dark:bg-slate-800">
							<div class="break-all font-mono text-sm text-slate-800 dark:text-slate-200">
								https://blanchon-robothub-frontend.hf.space<span class="bg-blue-100 text-blue-800 px-1 rounded dark:bg-blue-900 dark:text-blue-200">#{workspaceId}</span>
							</div>
						</div>
						<Button
							variant="outline"
							size="sm"
							onclick={copyUrl}
							class="w-full text-xs"
						>
							<span class="icon-[mdi--content-copy] mr-2 size-3"></span>
							Copy URL
						</Button>
					</div>
				</Card.Content>
			</Card.Root>

			<!-- Key Features -->
			<div class="space-y-3">
				<h3 class="text-sm font-semibold text-slate-700 dark:text-slate-300">What you can share:</h3>
				
				<div class="space-y-2 text-sm">
					<div class="flex items-start gap-2">
						<span class="icon-[mdi--video] size-4 text-green-500 mt-0.5 flex-shrink-0"></span>
						<span class="text-slate-600 dark:text-slate-400">
							<strong class="text-slate-800 dark:text-slate-200">Video Streams</strong> - Live camera feeds from connected devices
						</span>
					</div>
					
					<div class="flex items-start gap-2">
						<span class="icon-[mdi--robot] size-4 text-orange-500 mt-0.5 flex-shrink-0"></span>
						<span class="text-slate-600 dark:text-slate-400">
							<strong class="text-slate-800 dark:text-slate-200">Robot Control</strong> - Real-time teleoperation and monitoring
						</span>
					</div>
					
					<div class="flex items-start gap-2">
						<span class="icon-[mdi--brain] size-4 text-purple-500 mt-0.5 flex-shrink-0"></span>
						<span class="text-slate-600 dark:text-slate-400">
							<strong class="text-slate-800 dark:text-slate-200">AI Sessions</strong> - Shared inference and autonomous control
						</span>
					</div>
				</div>
			</div>

			<!-- Privacy & Security -->
			<Card.Root class="border-amber-300/30 bg-amber-100/10 dark:border-amber-500/30 dark:bg-amber-500/10">
				<Card.Content>
					<div class="flex items-start gap-2">
						<span class="icon-[mdi--shield-check] size-4 text-amber-600 mt-0.5 flex-shrink-0"></span>
						<div class="text-sm">
							<div class="font-medium text-amber-700 dark:text-amber-300 mb-1">Private Workspace</div>
							<div class="text-amber-600 dark:text-amber-400">
								Only users with this workspace ID can access your resources. Share it securely with trusted collaborators.
							</div>
						</div>
					</div>
				</Card.Content>
			</Card.Root>

			<!-- Use Cases -->
			<div class="rounded-lg border border-slate-300 bg-slate-50 p-3 dark:border-slate-600 dark:bg-slate-800">
				<div class="text-xs text-slate-600 dark:text-slate-400">
					<span class="icon-[mdi--lightbulb] mr-1 size-3"></span>
					<strong>Tip:</strong> Use this for remote teleoperation, collaborative research, demonstrations, or sharing your robot setup with team members across different networks.
				</div>
			</div>
		</div>
	</Dialog.Content>
</Dialog.Root>