Skip to content

Commit 53d44ba

Browse files
committed
feat(plugin): tidy payload row + use vueuse clipboard
Address review of the Activity payload inspector: - Drop the size from the collapsed row; show it only in the expanded header so the list stays clean. - Replace the hand-rolled copy (which silently no-op'd in the Figma iframe, where navigator.clipboard is undefined) with useClipboard({ legacy: true }), whose execCommand fallback works inside the plugin sandbox.
1 parent 12f6734 commit 53d44ba

1 file changed

Lines changed: 16 additions & 29 deletions

File tree

packages/plugin/ui/App.vue

Lines changed: 16 additions & 29 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,12 @@
11
<script setup lang="ts">
22
import { isPluginContextEvent, type PluginContextEvent, portRange } from '@figwright/shared';
3-
import { tryOnScopeDispose, useDocumentVisibility, useEventListener, useNow } from '@vueuse/core';
3+
import {
4+
tryOnScopeDispose,
5+
useClipboard,
6+
useDocumentVisibility,
7+
useEventListener,
8+
useNow,
9+
} from '@vueuse/core';
410
import { computed, onMounted, ref, watch } from 'vue';
511
612
import { createSandboxBridge } from './bridge/sandbox.js';
@@ -62,7 +68,6 @@ const errorEntries = computed(() => state.value.activity.filter(e => e.status ==
6268
6369
// Which Activity rows are expanded to show the payload fed to the LLM, and which just got copied.
6470
const expanded = ref<Set<string>>(new Set());
65-
const copiedId = ref<string | null>(null);
6671
6772
const toggle = (id: string): void => {
6873
const next = new Set(expanded.value);
@@ -74,29 +79,14 @@ const toggle = (id: string): void => {
7479
const formatSize = (bytes: number): string =>
7580
bytes < 1024 ? `${bytes} B` : `${(bytes / 1024).toFixed(1)} KB`;
7681
77-
// Copy the shown payload. navigator.clipboard is often blocked inside the Figma plugin iframe, so
78-
// fall back to a transient textarea + execCommand. Either way, flash a "copied" label.
82+
// Copy the shown payload. `legacy: true` makes useClipboard fall back to execCommand when the async
83+
// Clipboard API isn't available — which is the case inside the Figma plugin iframe. `copied` flips
84+
// true for ~1.5s after a copy; we pair it with the last-copied id so only that row's button flashes.
85+
const { copy: clipboardCopy, copied } = useClipboard({ legacy: true });
86+
const copiedId = ref<string | null>(null);
7987
const copy = (text: string, id: string): void => {
80-
const flash = (): void => {
81-
copiedId.value = id;
82-
setTimeout(() => {
83-
if (copiedId.value === id) copiedId.value = null;
84-
}, 1500);
85-
};
86-
void Promise.resolve(navigator.clipboard?.writeText(text))
87-
.catch(() => {
88-
const ta = document.createElement('textarea');
89-
ta.value = text;
90-
document.body.appendChild(ta);
91-
ta.select();
92-
try {
93-
document.execCommand('copy');
94-
} catch {
95-
/* nothing else to try */
96-
}
97-
ta.remove();
98-
})
99-
.finally(flash);
88+
copiedId.value = id;
89+
void clipboardCopy(text);
10090
};
10191
10292
const formatAgo = (ts: number): string => {
@@ -214,10 +204,7 @@ const runInBackground = (): void => {
214204
<span class="min-w-0 truncate" :class="e.status === 'error' ? 'text-fig-danger' : ''">
215205
{{ e.method }}
216206
</span>
217-
<span v-if="e.payload" class="ml-auto shrink-0 text-fig-muted">
218-
{{ formatSize(e.payload.bytes) }}
219-
</span>
220-
<span :class="['shrink-0 text-fig-muted', e.payload ? '' : 'ml-auto']">
207+
<span class="ml-auto shrink-0 text-fig-muted">
221208
{{ e.durationMs === undefined ? '' : `${e.durationMs}ms` }}
222209
</span>
223210
<span class="w-9 shrink-0 text-right text-fig-muted">{{
@@ -234,7 +221,7 @@ const runInBackground = (): void => {
234221
class="ml-auto shrink-0 rounded border border-white/15 px-1.5 py-0.5 hover:bg-white/10 hover:text-fig-fg"
235222
@click="copy(e.payload.preview, e.id)"
236223
>
237-
{{ copiedId === e.id ? 'copied' : 'copy' }}
224+
{{ copied && copiedId === e.id ? 'copied' : 'copy' }}
238225
</button>
239226
</div>
240227
<pre

0 commit comments

Comments
 (0)