0
Fork 0
mirror of https://github.com/penpot/penpot-plugins.git synced 2025-01-06 14:50:21 -05:00

refactor: remove old installer

This commit is contained in:
alonso.torres 2024-05-16 14:42:17 +02:00 committed by Alonso Torres
parent 5961469bf4
commit 2f2b5fcdf4
2 changed files with 0 additions and 338 deletions

View file

@ -1,6 +1,5 @@
import 'ses';
import './lib/plugin-modal';
import { initInstaller } from './lib/installer.js';
import { ɵloadPlugin, setContext } from './lib/load-plugin.js';
import * as api from './lib/api/index.js';
@ -22,7 +21,6 @@ globalThis.initPluginsRuntime = (context: PenpotContext) => {
/* eslint-disable */
globalThis.ɵcontext = context;
globalThis.ɵloadPlugin = ɵloadPlugin;
initInstaller();
setContext(context);

View file

@ -1,336 +0,0 @@
import { loadManifest } from './parse-manifest';
import { ɵloadPlugin } from './load-plugin';
const closeSvg = `
<svg width="16" height="16"xmlns="http://www.w3.org/2000/svg" fill="none"><g class="fills"><rect rx="0" ry="0" width="16" height="16" class="frame-background"/></g><g class="frame-children"><path d="M11.997 3.997 8 8l-3.997 4.003m-.006-8L8 8l4.003 3.997" class="fills"/><g class="strokes"><path d="M11.997 3.997 8 8l-3.997 4.003m-.006-8L8 8l4.003 3.997" style="fill: none; stroke-width: 1; stroke: rgb(143, 157, 163); stroke-opacity: 1; stroke-linecap: round;" class="stroke-shape"/></g></g></svg>`;
const pasteEventHandler = (event: ClipboardEvent) => {
const tagName = (event.target as HTMLElement).tagName;
if (tagName === 'INSTALLER-MODAL') {
event.stopImmediatePropagation();
}
};
export class InstallerElement extends HTMLElement {
constructor() {
super();
this.attachShadow({ mode: 'open' });
}
dialog: HTMLDialogElement | null = null;
createPlugin(pluginName: string, pluginUrl: string) {
const plugin = document.createElement('li');
plugin.classList.add('plugin');
plugin.textContent = pluginName;
const actions = document.createElement('div');
actions.classList.add('actions');
const openButton = document.createElement('button');
openButton.classList.add('button');
openButton.textContent = 'Open';
openButton.type = 'button';
openButton.addEventListener('click', () => {
this.closeModal();
void ɵloadPlugin({
manifest: pluginUrl,
});
});
actions.appendChild(openButton);
const removeButton = document.createElement('button');
removeButton.classList.add('button', 'remove');
removeButton.textContent = 'Remove';
removeButton.type = 'button';
removeButton.addEventListener('click', () => {
plugin.remove();
const plugins = this.getPlugins();
const newPlugins = plugins.filter((p) => p.url !== pluginUrl);
this.savePlugins(newPlugins);
});
actions.appendChild(removeButton);
plugin.appendChild(actions);
this.dialog?.querySelector<HTMLElement>('.plugins-list')?.prepend(plugin);
}
loadPluginList() {
const plugins = this.getPlugins();
for (const plugin of plugins) {
this.createPlugin(plugin.name, plugin.url);
}
}
getPlugins() {
const pluginsStorage = localStorage.getItem('plugins');
if (!pluginsStorage) {
return [];
}
return JSON.parse(pluginsStorage) as {
name: string;
url: string;
}[];
}
savePlugins(plugins: { name: string; url: string }[]) {
localStorage.setItem('plugins', JSON.stringify(plugins));
}
submitNewPlugin(event: Event) {
event.preventDefault();
const form = event.target as HTMLFormElement;
const input = form.querySelector('input') as HTMLInputElement;
if (!input) {
return;
}
const url = input.value;
input.value = '';
void loadManifest(url)
.then((manifest) => {
this.createPlugin(manifest.name, url);
const pluginsStorage = localStorage.getItem('plugins');
if (!pluginsStorage) {
localStorage.setItem(
'plugins',
JSON.stringify([{ name: manifest.name, url }])
);
} else {
const plugins = this.getPlugins();
plugins.push({ name: manifest.name, url });
this.savePlugins(plugins);
}
this.error(false);
})
.catch((error) => {
console.error(error);
this.error(true);
});
}
error(show: boolean) {
this.dialog?.querySelector('.error')?.classList.toggle('show', show);
}
connectedCallback() {
if (!this.shadowRoot) {
throw new Error('Error creating shadow root');
}
this.dialog = document.createElement('dialog');
this.dialog.innerHTML = `
<div class="header">
<h1>Plugins</h1>
<button type="button" class="close">${closeSvg}</button>
</div>
<form>
<input class="input url-input" placeholder="Plugin url" autofocus type="url" />
<button class="button" type="submit">Install</button>
</form>
<div class="error">
Error instaling plugin
</div>
<ul class="plugins-list"></ul>
`;
this.dialog.querySelector('.close')?.addEventListener('click', () => {
this.closeModal();
});
this.shadowRoot.appendChild(this.dialog);
this.dialog.addEventListener('submit', (event: Event) => {
this.submitNewPlugin(event);
});
this.loadPluginList();
const style = document.createElement('style');
style.textContent = `
* {
font-family worksans, sans-serif
}
::backdrop {
background-color: rgba(0, 0, 0, 0.8);
}
dialog {
border: 0;
width: 700px;
height: 500px;
padding: 20px;
background-color: white;
border-radius: 10px;
flex-direction: column;
display: none;
}
dialog[open] {
display: flex;
}
.header {
display: flex;
justify-content: space-between;
}
h1 {
margin: 0;
margin-block-end: 10px;
}
ul {
padding: 0;
}
li {
list-style: none;
}
.input {
display: flex;
border: 1px solid;
border-radius: calc( 0.25rem * 2);
font-size: 12px;
font-weight: 400;
line-height: 1.4;
outline: none;
padding-block: calc( 0.25rem * 2);
padding-inline: calc( 0.25rem * 2);
background-color: #f3f4f6;
border-color: #f3f4f6;
color: #000;
&:hover {
background-color: #eef0f2;
border-color: #eef0f2;
}
&:focus {
background-color: #ffffff
border-color: ##6911d4;
}
}
button {
background: transparent;
border: 0;
cursor: pointer;
}
.button {
border: 1px solid transparent;
font-weight: 500;
font-size: 12px;
border-radius: 8px;
line-height: 1.2;
padding: 8px 24px 8px 24px;
text-transform: uppercase;
background-color: #7EFFF5;
border: 1px solid 7EFFF5;
outline: 2px solid transparent;
&:hover:not(:disabled) {
cursor: pointer;
}
&:focus-visible {
outline: none;
}
}
.remove {
background-color: #ff3277;
border: 1px solid #ff3277;
outline: 2px solid transparent;
}
form {
display: flex;
gap: 10px;
margin-block-end: 20px;
}
.url-input {
inline-size: 400px;
}
.plugins-list {
display: flex;
flex-direction: column;
gap: 10px;
}
.plugin {
display: flex;
justify-content: space-between;
}
.actions {
display: flex;
gap: 10px;
}
.error {
display: none;
color: red;
&.show {
display: block;
}
}
`;
this.shadowRoot.appendChild(style);
}
closeModal() {
this.shadowRoot?.querySelector('dialog')?.close();
window.removeEventListener('paste', pasteEventHandler, true);
}
openModal() {
this.shadowRoot?.querySelector('dialog')?.showModal();
// prevent paste event in penpot workspace
window.addEventListener('paste', pasteEventHandler, true);
}
}
export function initInstaller() {
customElements.define('installer-modal', InstallerElement);
const modal = document.createElement('installer-modal');
document.body.appendChild(modal);
document.addEventListener('keydown', (event: KeyboardEvent) => {
if (event.key.toUpperCase() === 'I' && event.ctrlKey) {
document.querySelector<InstallerElement>('installer-modal')?.openModal();
}
});
}