Reading and writing a scenenode to the clipboard

How would one read and write a Scene node to the clipboard?

Here is what I’ve tried:

async function buttonClickHandler() {
	const {selection} = require("scenegraph");
	var item = selection.items[0];

    try {
        const clipboard = navigator.clipboard;

        // reading 
        var data = await clipboard.read();
        var content = await clipboard.getContent();
        var image = await clipboard.read("image/png");
        var content = await clipboard.getContent("scenenode");

        // writing 
        var result = await clipboard.setContent({"text/plain": "Hello!"});
        const clipboardItemInput = new ClipboardItem({'image/png' : item});
        var result = await clipboard.write([clipboardItemInput]);
    }
    catch(error) {
        console.log(error);
    }
}

All of the above fails except reading and writing text content.

Here’s the Adobe docs on it:

https://developer.adobe.com/photoshop/uxp/2022/uxp-api/reference-js/Global%20Members/Data%20Transfers/Clipboard/

Here’s the MDN docs on it:

I have not actually tried it in code, but perhaps that API needs to be granted in manifest v5. Was manifest v5 available in Adobe XD?

{
  "requiredPermissions": {
    "clipboard": "readAndWrite"
  }
}

And it seems like it needs ImageBlob to work. That has been supported since UXP v7.0.0, but XD is 6.3.0.

1 Like

I had almost the same issue and got no answer

regardless of what data you’re trying to access, clipboard only have plain text stored.

this is different from what docs state so must be a bug or incomplete

also I keep getting a warning about it being deprecated.

1 Like

I found that Adobe XD also supports manifest v5, and tried it with the permissions set.

I wrote code to copy the png image displayed in the panel to the clipboard, but it seems that the necessary data type is not defined. Does this require something external?

const targetButton = document.getElementById('button-copy') ;
const targetImage = document.getElementById('image') ;
console.log(targetImage.src) ;
// --> images/icon@2x.png

const getBlobFromImage = async (url) => {
  return fetch(url).then((response) => {return response.blob()}) ;
} ;

const copyImageToClipboard = async (url) => {
  const blob = await getBlobFromImage(url) ;
  console.log(blob) ;
  // --> a {Symbol(nativeBlob): {…}}

  // 1. ClipboardItem
  try {
    console.log('1. ClipboardItem') ;
    const { type } = blob ;
    await navigator.clipboard.write( [new ClipboardItem({[type]: blob})] ) ;
  } catch(e) {
    console.log(e) ;
  }
  // --> ReferenceError: ClipboardItem is not defined

  // 2. DataTransfer
  try {
    console.log('2. DataTransfer') ;
    const dataTransfer = new DataTransfer() ;
    dataTransfer.items.add(new DataTransferItem('icon@2x.png', blob)) ;
    await navigator.clipboard.write(dataTransfer) ;
  } catch(e) {
    console.log(e) ;
  }
  // --> ReferenceError: DataTransfer is not defined

  // 3. ClipboardEvent.clipboardData
  try {
    console.log('3. ClipboardEvent.clipboardData') ;
    const dataTransfer = new ClipboardEvent('').clipboardData ;
    console.log(dataTransfer) ;
    // --> e.exports {Symbol(impl): a}

    dataTransfer.items.add(new DataTransferItem('icon@2x.png', blob)) ;
    await navigator.clipboard.write(dataTransfer) ;
  } catch(e) {
    console.log(e) ;
  }
  // --> ReferenceError: DataTransferItem is not defined
} ;

targetButton.onclick = async () => {
  await copyImageToClipboard(targetImage.src) ;
} ;
1 Like