From 76ff193e4fa52831fd16a56643dc2eb190f7d36a Mon Sep 17 00:00:00 2001 From: "alonso.torres" Date: Tue, 24 Sep 2024 14:44:19 +0200 Subject: [PATCH] feat(poc-state-plugin): add new functions to the plugin to test comments and rulers --- .../poc-state-plugin/src/app/app.component.ts | 54 ++++++++++++++++ .../poc-state-plugin/src/assets/manifest.json | 6 +- apps/poc-state-plugin/src/plugin.ts | 61 ++++++++++++++++++- libs/plugin-types/index.d.ts | 2 +- .../src/lib/plugin-manager.spec.ts | 3 +- 5 files changed, 120 insertions(+), 6 deletions(-) diff --git a/apps/poc-state-plugin/src/app/app.component.ts b/apps/poc-state-plugin/src/app/app.component.ts index 2e9bc856..64300c41 100644 --- a/apps/poc-state-plugin/src/app/app.component.ts +++ b/apps/poc-state-plugin/src/app/app.component.ts @@ -90,6 +90,28 @@ import type { Shape } from '@penpot/plugin-types'; > Rotate + + + + @@ -146,6 +168,8 @@ export class AppComponent { this.theme.set(event.data.content); } else if (event.data.type === 'update-counter') { this.counter.set(event.data.content.counter); + } else if (event.data.type === 'start-download') { + this.#startDownload(event.data.content); } }); @@ -218,6 +242,18 @@ export class AppComponent { this.#sendMessage({ content: 'rotate-selection' }); } + createMargins() { + this.#sendMessage({ content: 'create-margins' }); + } + + addComment() { + this.#sendMessage({ content: 'add-comment' }); + } + + exportFile() { + this.#sendMessage({ content: 'export-file' }); + } + async uploadImage(event: Event) { const input = event.target as HTMLInputElement; if (input?.files?.length) { @@ -253,4 +289,22 @@ export class AppComponent { this.form.get('name')?.setValue(''); } } + + #startDownload(data: Uint8Array) { + const blob = new Blob([data], { type: 'application/octet-stream' }); + + // We need to start a download with this URL + const downloadURL = URL.createObjectURL(blob); + + // Download + var a = document.createElement('a'); + document.body.appendChild(a); + a.href = downloadURL; + a.download = 'Export.penpot'; + a.click(); + + // Remove temporary + URL.revokeObjectURL(a.href); + a.remove(); + } } diff --git a/apps/poc-state-plugin/src/assets/manifest.json b/apps/poc-state-plugin/src/assets/manifest.json index ce29e9c2..5a2ba40c 100644 --- a/apps/poc-state-plugin/src/assets/manifest.json +++ b/apps/poc-state-plugin/src/assets/manifest.json @@ -3,10 +3,10 @@ "description": "Sandbox plugin for plugins development", "code": "/assets/plugin.js", "permissions": [ - "content:read", "content:write", - "library:read", "library:write", - "user:read" + "comment:write", + "user:read", + "allow:downloads" ] } diff --git a/apps/poc-state-plugin/src/plugin.ts b/apps/poc-state-plugin/src/plugin.ts index d8b704ba..ed8e3151 100644 --- a/apps/poc-state-plugin/src/plugin.ts +++ b/apps/poc-state-plugin/src/plugin.ts @@ -5,7 +5,7 @@ penpot.ui.open('Plugin name', '', { height: 600, }); -penpot.ui.onMessage<{ content: string; data: unknown }>((message) => { +penpot.ui.onMessage<{ content: string; data: unknown }>(async (message) => { if (message.content === 'close') { penpot.closePlugin(); } else if (message.content === 'ready') { @@ -42,6 +42,12 @@ penpot.ui.onMessage<{ content: string; data: unknown }>((message) => { mimeType: string; }; createImage(data, mimeType); + } else if (message.content === 'create-margins') { + createMargins(); + } else if (message.content === 'add-comment') { + addComment(); + } else if (message.content === 'export-file') { + exportFile(); } }); @@ -432,3 +438,56 @@ function createImage(data: Uint8Array, mimeType: string) { }) .catch((err) => console.error(err)); } + +function createMargins() { + const page = penpot.currentPage; + const selected = penpot.selection && penpot.selection[0]; + + if (selected && penpot.utils.types.isBoard(selected)) { + const { width, height } = selected; + selected.addRulerGuide('vertical', 10); + selected.addRulerGuide('vertical', width - 10); + selected.addRulerGuide('horizontal', 10); + selected.addRulerGuide('horizontal', height - 10); + } else { + console.log('bound', penpot.viewport.bounds); + const { x, y, width, height } = penpot.viewport.bounds; + page.addRulerGuide('vertical', x + 100); + page.addRulerGuide('vertical', x + width - 50); + page.addRulerGuide('horizontal', y + 100); + page.addRulerGuide('horizontal', y + height - 50); + } +} + +async function addComment() { + const shape = penpot.selection[0]; + + if (shape) { + const content = shape.name + ' - ' + Date.now(); + const cthr = await penpot.currentPage.findCommentThreads(); + const th = cthr && cthr[0]; + + if (th) { + const comms = await th.findComments(); + const first = comms && comms[0]; + if (first) { + console.log('Reply to thread', content); + th.reply(content); + } + } else { + console.log('Create new thread', content); + await penpot.currentPage.addCommentThread(content, shape.center); + } + } +} + +async function exportFile() { + const data = await penpot.getFile()?.export('penpot'); + + if (data) { + penpot.ui.sendMessage({ + type: 'start-download', + content: data, + }); + } +} diff --git a/libs/plugin-types/index.d.ts b/libs/plugin-types/index.d.ts index 4396672b..f6b6ed44 100644 --- a/libs/plugin-types/index.d.ts +++ b/libs/plugin-types/index.d.ts @@ -2850,7 +2850,7 @@ export interface Page extends PluginData { /** * Removes the comment thread. - * Requires the `comment:read` or `comment:write` permission. + * Requires the `comment:write` permission. */ removeCommentThread(commentThread: CommentThread): Promise; diff --git a/libs/plugins-runtime/src/lib/plugin-manager.spec.ts b/libs/plugins-runtime/src/lib/plugin-manager.spec.ts index f9ae2295..18c5a5a2 100644 --- a/libs/plugins-runtime/src/lib/plugin-manager.spec.ts +++ b/libs/plugins-runtime/src/lib/plugin-manager.spec.ts @@ -114,7 +114,8 @@ describe('createPluginManager', () => { 'Test Modal', 'https://example.com/plugin', 'light', - { width: 400, height: 300 } + { width: 400, height: 300 }, + true ); expect(mockModal.setTheme).toHaveBeenCalledWith('light'); expect(mockModal.addEventListener).toHaveBeenCalledWith(