Add image export support.

This commit is contained in:
Paulo Gustavo Veiga 2023-01-14 22:41:32 -08:00
parent e54d4ff543
commit d1e52d8f05
6 changed files with 38 additions and 22 deletions

View File

@ -47,6 +47,9 @@
"appbar.tooltip-undo": {
"defaultMessage": "Undo"
},
"editor-panel.icon-title": {
"defaultMessage": "Icon"
},
"editor-panel.link-panel-title": {
"defaultMessage": "Link"
},
@ -158,9 +161,6 @@
"icon-picker.show-images": {
"defaultMessage": "Show images"
},
"editor-panel.icon-title": {
"defaultMessage": "Icon"
},
"link.help_text": {
"defaultMessage": "Address is not valid"
},
@ -195,7 +195,7 @@
"defaultMessage": "Collpase children"
},
"shortcut-help-pane.copy-and-text": {
"defaultMessage": "Copy and paste topics"
"defaultMessage": "Copy and paste topics/Copy mindmap image to clipboard."
},
"shortcut-help-pane.delete-topic": {
"defaultMessage": "Delete topic"

View File

@ -133,7 +133,7 @@ const KeyboardShorcutsHelp = (): ReactElement => {
<td>
<FormattedMessage
id="shortcut-help-pane.copy-and-text"
defaultMessage="Copy and paste topics"
defaultMessage="Copy and paste topics/Copy mindmap image to clipboard."
/>
</td>
<td>Ctrl + C / Ctrl + V</td>

View File

@ -57,6 +57,7 @@ import WidgetManager from './WidgetManager';
import { TopicShapeType } from './model/INodeModel';
import { LineType } from './ConnectionLine';
import XMLSerializerFactory from './persistence/XMLSerializerFactory';
import ImageExpoterFactory from './export/ImageExporterFactory';
class Designer extends Events {
private _mindmap: Mindmap | null;
@ -377,7 +378,7 @@ class Designer extends Events {
}
}
copyToClipboard(): void {
async copyToClipboard(): Promise<void> {
let topics = this.getModel().filterSelectedTopics();
if (topics.length > 0) {
const mindmap = new Mindmap();
@ -391,19 +392,34 @@ class Designer extends Events {
nodeModel.connectTo(central);
});
// Serialize to mindmap ...
// Create text blob ...
const serializer = XMLSerializerFactory.createFromMindmap(mindmap);
const document = serializer.toXML(mindmap);
const xmmStr: string = new XMLSerializer().serializeToString(document);
const xmlStr: string = new XMLSerializer().serializeToString(document);
const textPlainBlob = new Blob([xmlStr], { type: 'text/plain' });
// Convert to node, only text/html is supported...
const type = 'text/plain';
const blob = new Blob([xmmStr], { type });
// Create image blob ...
const workspace = designer.getWorkSpace();
const svgElement = workspace.getSVGElement();
const size = { width: window.innerWidth, height: window.innerHeight };
const imageUrl = ImageExpoterFactory.create(
'png',
svgElement,
size.width,
size.height,
false,
);
let imgStr = await imageUrl.exportAndEncode();
imgStr = imgStr.replace('octet/stream', 'image/png');
const imgBlob = await (await fetch(imgStr)).blob();
// Finally, add to clipboard ...
const clipboard = new ClipboardItem({
[blob.type]: blob,
[textPlainBlob.type]: textPlainBlob,
[imgBlob.type]: imgBlob,
});
// Copy to clipboard ...
navigator.clipboard.write([clipboard]).then(
() => console.log('Copy of node success'),
(e) => console.error(e),

View File

@ -44,7 +44,7 @@ class BinaryImageExporter extends Exporter {
}
export(): Promise<string> {
throw new Error('Images can not be exporeted');
throw new Error('Images can not be exported');
}
exportAndEncode(): Promise<string> {

View File

@ -25,12 +25,10 @@ abstract class Exporter {
this._contentType = contentType;
}
exportAndEncode(): Promise<string> {
const exportValue = this.export();
return exportValue.then((value: string) => {
const blob = new Blob([value], { type: this._contentType });
return URL.createObjectURL(blob);
});
async exportAndEncode(): Promise<string> {
const exportValue = await this.export();
const blob = new Blob([exportValue], { type: this._contentType });
return URL.createObjectURL(blob);
}
abstract export(): Promise<string>;

View File

@ -127,8 +127,10 @@ const ExportDialog = ({
exporter = TextExporterFactory.create(formatType, mindmap);
break;
}
default:
throw new Error('Unsupported encoding');
default: {
const exhaustiveCheck: never = formatType;
throw new Error(`Unhandled color case: ${exhaustiveCheck}`);
}
}
return exporter.exportAndEncode();