From 6b921292590400daf67cd2300139322b08f79d67 Mon Sep 17 00:00:00 2001 From: xsrf Date: Sun, 11 Apr 2021 18:08:45 +0200 Subject: [PATCH] flip arrow-keys; use easyeda-helper.js --- extension/easyeda-helper.js | 127 +++++++++++++++++++++++++ extension/main.js | 180 ++++++++++++++---------------------- extension/manifest.json | 4 +- 3 files changed, 197 insertions(+), 114 deletions(-) create mode 100644 extension/easyeda-helper.js diff --git a/extension/easyeda-helper.js b/extension/easyeda-helper.js new file mode 100644 index 0000000..dc8bbe9 --- /dev/null +++ b/extension/easyeda-helper.js @@ -0,0 +1,127 @@ +/* + Common Helper Functions for EasyEDA API +*/ +const extensionId = Object.entries(easyeda.extension.instances).filter(e => e[1].blobURLs && e[1].blobURLs['manifest.json'] == api('getRes',{file:'manifest.json'}))[0][1].id; +const instance = easyeda.extension.instances[extensionId]; + +instance.Helper = class Helper { + + static createCommand(callback) { + const id = 'extension-' + extensionId + '-' + Math.round(Math.random()*1e9); + let cmd={}; + cmd[id] = callback; + api('createCommand', cmd); + return id; + } + + static async loadExtensionModule(filename) { + try { + const url = api('getRes',{file: filename}); + if(!url) throw 'blob-url undefined'; + return await import(url); + } catch (error) { + const msg = `Failed to load module '${filename}' of extension '${extensionId}'. Maybe you didn't select all files for install?! Please reinstall! ${error}`; + $.messager.error(msg); + throw msg; + } + } + + static async loadExtensionScript(filename) { + try { + const response = await fetch(api('getRes',{file: filename})); + const body = await response.text(); + return eval(body); + } catch (error) { + const msg = `Failed to load script '${filename}' of extension '${extensionId}'. Maybe you didn't select all files for install?! Please reinstall! ${error}`; + $.messager.error(msg); + throw msg; + } + } + + static async getExtensionScript(filename) { + try { + const url = api('getRes',{file: filename}); + if(!url) throw 'blob-url undefined'; + const response = await fetch(url); + const body = await response.text(); + return body; + } catch (error) { + const msg = `Failed to load script '${filename}' of extension '${extensionId}'. Maybe you didn't select all files for install?! Please reinstall! ${error}`; + $.messager.error(msg); + throw msg; + } + } + + static setConfig(key,value) { + var conf = {}; + try { + conf = localStorage.getItem(`extension.${extensionId}.config`) || '{}'; + conf = JSON.parse(conf); + } catch (error) { + conf = {}; + } + conf[key] = value; + if(value === null) delete conf[value]; + localStorage.setItem(`extension.${extensionId}.config`,JSON.stringify(conf)); + } + + static getConfig(key,defaultValue) { + try { + var conf = localStorage.getItem(`extension.${extensionId}.config`) || '{}'; + conf = JSON.parse(conf); + if(!(key in conf)) return defaultValue; + return conf[key]; + } catch (error) { + return defaultValue; + } + } + + static checkUpdate() { + (async ()=>{ + try { + if(!('version' in instance.manifest)) return; + if(!('homepage' in instance.manifest)) return; + if(!('updatebaseurl' in instance.manifest)) return; + var skipVersion = this.getConfig('update-skip',instance.manifest.version); + var cmdUpdatePage = this.createCommand(()=>{ window.open(instance.manifest.homepage,'_blank') }); + var cmdUpdateSkip = this.createCommand(()=>{ this.setConfig('update-skip',skipVersion) }); + var response = await fetch(instance.manifest.updatebaseurl + 'manifest.json'); + if(response.status != 200) { + console.log('Update check failed, Status: ' + response.status); + return; + } + var onlineManifest = await response.json(); + if(onlineManifest.version == instance.manifest.version) { + console.log(`Update check ok, "${extensionId}" is up to date`); + return; + } + if(onlineManifest.version == skipVersion) { + console.log(`Update check ok, "${extensionId}" is not up to date but version is skipped`); + return; + } + console.log(`Update check ok, "${extensionId}" is not up to date`); + skipVersion = onlineManifest.version; + $.messager.show({ + title: `Update Available for ${instance.manifest.name}`, + msg: ` + + +
Installed:${instance.manifest.name} ${instance.manifest.version}
Available:${onlineManifest.name} ${onlineManifest.version}
+
+ Download + Skip Version +
+ `, + height: 'auto', + timeout: 30e3, + showType: "slide" + }); + } catch (error) { + console.log('Update check failed: '+error); + } + })(); + } + +} + +console.log(`EasyEDA Helper loaded for extension "${extensionId}"`); \ No newline at end of file diff --git a/extension/main.js b/extension/main.js index 0dc4a8a..33847fb 100644 --- a/extension/main.js +++ b/extension/main.js @@ -1,46 +1,9 @@ const extensionId = 'extension-toggleview-id'.split('-')[1]; // this format is needed to set the Extension ID during install const manifest = easyeda.extension.instances[extensionId].manifest; const instance = easyeda.extension.instances[extensionId]; -var defaultFlipped = false; - +const Helper = instance.Helper; // Helper class declared in easyeda-helper.js -/* - Self-Contained Update-Notification. - Relies on "instance" pointing to easyeda.extension.instances[extensionId] - "updatebaseurl" being set in the manifest - "homepage" being set in the manifest -*/ -(async ()=>{ - try { - var skipVersion = localStorage.getItem(`extension-${instance.id}-update-skip`) || instance.manifest.version; - var cmds = {}; - cmds[`extension-${instance.id}-update-page`] = ()=>{ window.open(instance.manifest.homepage,'_blank') }; - cmds[`extension-${instance.id}-update-skip`] = ()=>{ localStorage.setItem(`extension-${instance.id}-update-skip`,skipVersion) }; - api('createCommand', cmds); - var response = await fetch(instance.manifest.updatebaseurl + 'manifest.json'); - var onlineManifest = await response.json(); - if(onlineManifest.version != instance.manifest.version && onlineManifest.version != skipVersion) { - skipVersion = onlineManifest.version; - $.messager.show({ - title: `Update Available for ${instance.manifest.name}`, - msg: ` - - -
Installed:${instance.manifest.name} ${instance.manifest.version}
Available:${onlineManifest.name} ${onlineManifest.version}
-
- Download - Skip Version -
- `, - height: 'auto', - timeout: 30e3, - showType: "slide" - }); - } - } catch (error) { - console.log('Update check failed: '+error); - } -})(); +var defaultFlipped = false; api('createToolbarButton', { icon: api('getRes', { file: 'icon.svg' }), @@ -49,48 +12,49 @@ api('createToolbarButton', { menu:[ { text: "Toggle View", - cmd: createCommand(()=>{toggle();}), + cmd: Helper.createCommand(()=>{toggle();}), title: 'Toggle PCB View between Top and Bottom', icon: api('getRes', { file: 'icon.svg' }) }, { text: 'Flip on Layer', + title: 'Flip view automatically for these Layers', submenu: [ { text: 'Bottom Copper', group: 'checkbox:autoToggleLayer', id: `${extensionId}-layer-2`, - cmd: createCommand(()=>{saveConfig()}) + cmd: Helper.createCommand(()=>{saveConfig()}) }, { text: 'Bottom Silk', group: 'checkbox:autoToggleLayer', id: `${extensionId}-layer-4`, - cmd: createCommand(()=>{saveConfig()}) + cmd: Helper.createCommand(()=>{saveConfig()}) }, { text: 'Bottom Paste', group: 'checkbox:autoToggleLayer', id: `${extensionId}-layer-6`, - cmd: createCommand(()=>{saveConfig()}) + cmd: Helper.createCommand(()=>{saveConfig()}) }, { text: 'Bottom Mask', group: 'checkbox:autoToggleLayer', id: `${extensionId}-layer-8`, - cmd: createCommand(()=>{saveConfig()}) + cmd: Helper.createCommand(()=>{saveConfig()}) } ] }, {}, { text: "Visit GitHub Page", - cmd: createCommand(()=>{ window.open(manifest.homepage,'_blank'); }), + cmd: Helper.createCommand(()=>{ window.open(manifest.homepage,'_blank'); }), icon: "data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAYAAAAf8/9hAAAABGdBTUEAAK/INwWK6QAAABl0RVh0U29mdHdhcmUAQWRvYmUgSW1hZ2VSZWFkeXHJZTwAAAFxSURBVHjajNPNK0RhFMfxe2dI04y8NExNNmzJ2igRWwtlRRllryz8DVhYiKLZaHbyWv4ALyHCgvwBQyEW5GVhphDfU7+rJ0n31Gfufe4959w7z3MfP1VX7/2KLgygHQ26doNDLGHXTfadBjWYxoj3fyxiHE82iDjFGyGKPeVsqMaLJuJxOy6gD0eYQhJVuMIjKnCOSdSiAylslvHTiWF1v8C8XrMaz7oenJfQioxq8tYga3OhxJJzvHde2z0PcqwmG1E3izfkQsxBTrkWGWuQ1uABhRANCsq1SFuDLw0SiIVoEFOuxZc1uNbAZrcnRIPuYAmt1hocaPCKGS2R/0ehr3vTzv19a5DXYBlb2MMx2pxim+ht7KBR1z6CZTzBHEbRi0s049Zp8KI94obVnAZ7wSZmBS0YU/EZPpWc1OxXaryOIRSDvVBEP9awqr+QdJ4WVbHlTWBQ5z97wdPTbKveaWnXna+uHE167Vm8B0XfAgwAj8RQQEL6HPwAAAAASUVORK5CYII=" }, { text: "About", - cmd: createCommand(()=>{ aboutdlg.dialog('open') }) + cmd: Helper.createCommand(()=>{ aboutdlg.dialog('open') }) }, ] }); @@ -116,7 +80,7 @@ var aboutdlg = api('createDialog', { ] }); -const flipmousevent = (e) => { +function flipmousevent(e) { if(e.isTrusted) { e.stopImmediatePropagation(); w = e.target.clientWidth; @@ -141,33 +105,42 @@ const flipmousevent = (e) => { } } -function createCommand(callback) { - id = 'extension-'+extensionId+'-' + Math.round(Math.random()*1e9); - cmd=[]; - cmd[id] = callback; - api('createCommand', cmd); - return id; -} - -// listen to layer change -/* -const classObserver = new MutationObserver((mutations) => { - mutations.forEach(mu => { - if (mu.type !== "attributes" && mu.attributeName !== "class") return; - active = mu.target.classList.contains('active'); - if(active) layerChanged(); - }); -}); - -const initObserverX = () => { - let elements = document.querySelectorAll('#toolbar-pcblayer-tbl tr[layer_id]'); - elements.forEach((el)=>{ - classObserver.observe(el, {attributes: true}); - }); +function flipkeyboardevent(e) { + if(!e.isTrusted) return; + if(!['ArrowRight','ArrowLeft'].includes(e.key)) return; + f = new KeyboardEvent(e.type, { + altKey: e.altKey, + bubbles: e.bubbles, + cancelBubble: e.cancelBubble, + cancelable: e.cancelable, + charCode: e.charCode, + code: e.code == 'ArrowRight' ? 'ArrowLeft':'ArrowRight', + composed: e.composed, + ctrlKey: e.ctrlKey, + currentTarget: e.currentTarget, + defaultPrevented: e.defaultPrevented, + detail: e.detail, + eventPhase: e.eventPhase, + isComposing: e.isComposing, + key: e.key == 'ArrowRight' ? 'ArrowLeft':'ArrowRight', + keyCode: e.keyCode == 39 ? 37 : 39, + location: e.location, + metaKey: e.metaKey, + path: e.path, + repeat: e.repeat, + returnValue: e.returnValue, + shiftKey: e.shiftKey, + sourceCapabilities: e.sourceCapabilities, + srcElement: e.srcElement, + target: e.target, + view: e.view, + which: e.which == 39 ? 37 : 39, + }) + e.stopImmediatePropagation(); + e.target.dispatchEvent(f); } -*/ -const initObserver = () => { +function initObserver() { setInterval(()=>{ instance.activeLayer = instance.activeLayer || -1; activeLayer = getActiveLayerId(); @@ -178,22 +151,22 @@ const initObserver = () => { },1e2); } -const layerChanged = () => { +function layerChanged() { layerId = getActiveLayerId(); setFlipped(defaultFlipped || isAutoToggleOnLayer(layerId)); } -const setAutoToggleOnLayer = (layerId,checked) => { +function setAutoToggleOnLayer(layerId,checked) { let selector = `#${extensionId}-layer-${layerId}`; $(selector).menu('setChecked',{target:$(selector),checked: !!checked}); } -const isAutoToggleOnLayer = (layerId) => { +function isAutoToggleOnLayer(layerId) { let selector = `#${extensionId}-layer-${layerId}`; return $(selector).menu('isChecked'); } -const setFlipped = (flipped) => { +function setFlipped(flipped) { if(getFlipped() == flipped) return; tab = document.querySelectorAll('#tabbar_bodies div[uuid]').filter(e=>e.style.display=='block')[0]; // get active tab if(!tab) return; @@ -202,21 +175,27 @@ const setFlipped = (flipped) => { rulerc = tab.querySelector('.rulerhc'); if(!editor) return; if(!flipped) { - editor.removeEventListener ('mousemove',flipmousevent,{capture: true}); + editor.removeEventListener('mousemove',flipmousevent,{capture: true}); editor.removeEventListener('mouseup',flipmousevent,{capture: true}); editor.removeEventListener('mousedown',flipmousevent,{capture: true}); + editor.contentDocument.removeEventListener('keydown',flipkeyboardevent,{capture: true}); + editor.contentDocument.removeEventListener('keyup',flipkeyboardevent,{capture: true}); + editor.contentDocument.removeEventListener('keypress',flipkeyboardevent,{capture: true}); editor.style.transform = ''; ruler.style.transform = ''; } else { editor.addEventListener('mousemove',flipmousevent,{capture: true}); editor.addEventListener('mouseup',flipmousevent,{capture: true}); editor.addEventListener('mousedown',flipmousevent,{capture: true}); + editor.contentDocument.addEventListener('keydown',flipkeyboardevent,{capture: true}); + editor.contentDocument.addEventListener('keyup',flipkeyboardevent,{capture: true}); + editor.contentDocument.addEventListener('keypress',flipkeyboardevent,{capture: true}); editor.style.transform = 'scaleX(-1)'; ruler.style.transform = 'scaleX(-1)'; } } -const getFlipped = () => { +function getFlipped() { obj = document.querySelectorAll('#tabbar_bodies div[uuid]').filter(e=>e.style.display=='block')[0]; // get active tab if(!obj) return; obj = obj.querySelector('iframe'); @@ -224,51 +203,28 @@ const getFlipped = () => { return obj.style.transform == 'scaleX(-1)'; } -const toggle = () => { +function toggle() { defaultFlipped = !getFlipped(); setFlipped(defaultFlipped); } -const getActiveLayerId = () => { +function getActiveLayerId() { return $('#toolbar-pcblayer-tbl tr.active').attr('layer_id'); } -function setConfig(key,value) { - var conf = {}; - try { - conf = localStorage.getItem(`extension.${extensionId}.config`) || '{}'; - conf = JSON.parse(conf); - } catch (error) { - conf = {}; - } - conf[key] = value; - if(value === null) delete conf[value]; - localStorage.setItem(`extension.${extensionId}.config`,JSON.stringify(conf)); -} - -function getConfig(key,defaultValue) { - try { - var conf = localStorage.getItem(`extension.${extensionId}.config`) || '{}'; - conf = JSON.parse(conf); - if(!(key in conf)) return defaultValue; - return conf[key]; - } catch (error) { - return defaultValue; - } -} - function saveConfig() { - setConfig('layer-2',isAutoToggleOnLayer(2)); - setConfig('layer-4',isAutoToggleOnLayer(4)); - setConfig('layer-6',isAutoToggleOnLayer(6)); - setConfig('layer-8',isAutoToggleOnLayer(8)); + Helper.setConfig('layer-2',isAutoToggleOnLayer(2)); + Helper.setConfig('layer-4',isAutoToggleOnLayer(4)); + Helper.setConfig('layer-6',isAutoToggleOnLayer(6)); + Helper.setConfig('layer-8',isAutoToggleOnLayer(8)); } function init() { - setAutoToggleOnLayer(2,getConfig('layer-2',false)); - setAutoToggleOnLayer(4,getConfig('layer-4',false)); - setAutoToggleOnLayer(6,getConfig('layer-6',false)); - setAutoToggleOnLayer(8,getConfig('layer-8',false)); + Helper.checkUpdate(); + setAutoToggleOnLayer(2,Helper.getConfig('layer-2',false)); + setAutoToggleOnLayer(4,Helper.getConfig('layer-4',false)); + setAutoToggleOnLayer(6,Helper.getConfig('layer-6',false)); + setAutoToggleOnLayer(8,Helper.getConfig('layer-8',false)); initObserver(); layerChanged(); } diff --git a/extension/manifest.json b/extension/manifest.json index 1ad58cf..6a297dc 100644 --- a/extension/manifest.json +++ b/extension/manifest.json @@ -1,11 +1,11 @@ { "name": "ToggleView", "description": "Allows you to switch the PCB View between Top and Bottom View.", - "version": "1.1", + "version": "1.2", "homepage": "https://github.com/xsrf/easyeda-toggleview", "icons": { "default": "icon.svg" }, - "scripts": [ "main.js" ], + "scripts": [ "easyeda-helper.js", "main.js" ], "updatebaseurl" : "https://raw.githubusercontent.com/xsrf/easyeda-toggleview/autoupdate/extension/" }