diff options
author | neauoire <[email protected]> | 2019-11-05 17:06:33 -0500 |
---|---|---|
committer | neauoire <[email protected]> | 2019-11-05 17:06:33 -0500 |
commit | adeb472132cb0851eb430fa17c6105ec1bdbbfe3 (patch) | |
tree | 108dba74ec70aad2fa5232d1af485ccbc6b3e406 /desktop/sources/scripts/lib | |
parent | f3abf65191e9e0d6059cd95d4ed7d4e818424fa9 (diff) | |
download | Orca-adeb472132cb0851eb430fa17c6105ec1bdbbfe3.tar.gz Orca-adeb472132cb0851eb430fa17c6105ec1bdbbfe3.zip |
Working on web version
Diffstat (limited to 'desktop/sources/scripts/lib')
-rw-r--r-- | desktop/sources/scripts/lib/acels.js | 123 | ||||
-rw-r--r-- | desktop/sources/scripts/lib/controller.js | 81 | ||||
-rw-r--r-- | desktop/sources/scripts/lib/history.js | 74 | ||||
-rw-r--r-- | desktop/sources/scripts/lib/theme.js | 58 |
4 files changed, 224 insertions, 112 deletions
diff --git a/desktop/sources/scripts/lib/acels.js b/desktop/sources/scripts/lib/acels.js new file mode 100644 index 0000000..962d58e --- /dev/null +++ b/desktop/sources/scripts/lib/acels.js @@ -0,0 +1,123 @@ +'use strict' + +function Acels () { + this.all = {} + this.pipe = null + + this.install = (host = window) => { + host.addEventListener('keydown', this.onKeyDown, false) + host.addEventListener('keyup', this.onKeyUp, false) + } + + this.set = (cat, name, accelerator, downfn, upfn) => { + if (this.all[accelerator]) { console.warn('Acels', `Trying to overwrite ${this.all[accelerator].name}, with ${name}.`) } + this.all[accelerator] = { cat, name, downfn, upfn, accelerator } + } + + this.get = (accelerator) => { + return this.all[accelerator] + } + + this.sort = () => { + const h = {} + for (const item of Object.values(this.all)) { + if (!h[item.cat]) { h[item.cat] = [] } + h[item.cat].push(item) + } + return h + } + + this.convert = (event) => { + const accelerator = event.key === ' ' ? 'Space' : event.key.substr(0, 1).toUpperCase() + event.key.substr(1) + if ((event.ctrlKey || event.metaKey) && event.shiftKey) { + return `CmdOrCtrl+Shift+${accelerator}` + } + if (event.shiftKey) { + return `Shift+${accelerator}` + } + if (event.altKey) { + return `Alt+${accelerator}` + } + if (event.ctrlKey || event.metaKey) { + return `CmdOrCtrl+${accelerator}` + } + return accelerator + } + + this.pipe = (obj) => { + this.pipe = obj + } + + this.onKeyDown = (e) => { + const target = this.get(this.convert(e)) + if (!target || !target.downfn) { return this.pipe ? this.pipe.onKeyDown(e) : null } + target.downfn() + e.preventDefault() + } + + this.onKeyUp = (e) => { + const target = this.get(this.convert(e)) + if (!target || !target.upfn) { return this.pipe ? this.pipe.onKeyUp(e) : null } + target.upfn() + e.preventDefault() + } + + this.toMarkdown = () => { + const cats = this.sort() + let text = '' + for (const cat in cats) { + text += `\n### ${cat}\n\n` + for (const item of cats[cat]) { + text += `- \`${item.accelerator}\`: ${item.info}\n` + } + } + return text.trim() + } + + this.toString = () => { + const cats = this.sort() + let text = '' + for (const cat in cats) { + for (const item of cats[cat]) { + text += `${cat}: ${item.name} | ${item.accelerator}\n` + } + } + return text.trim() + } + + // Electron specifics + + this.inject = (name = 'Untitled') => { + const app = require('electron').remote.app + const injection = [] + + injection.push({ + label: name, + submenu: [ + { label: 'About', click: () => { require('electron').shell.openExternal('https://github.com/hundredrabbits/' + name) } }, + { label: 'Download Themes', click: () => { require('electron').shell.openExternal('https://github.com/hundredrabbits/Themes') } }, + { label: 'Fullscreen', accelerator: 'CmdOrCtrl+Enter', click: () => { app.toggleFullscreen() } }, + { label: 'Hide', accelerator: 'CmdOrCtrl+H', click: () => { app.toggleVisible() } }, + { label: 'Toggle Menubar', accelerator: 'Alt+H', click: () => { app.toggleMenubar() } }, + { label: 'Inspect', accelerator: 'CmdOrCtrl+.', click: () => { app.inspect() } }, + { label: 'Quit', accelerator: 'CmdOrCtrl+Q', click: () => { app.exit() } } + ] + }) + + const sorted = this.sort() + for (const cat of Object.keys(sorted)) { + const submenu = [] + for (const option of sorted[cat]) { + if (option.role) { + submenu.push({ role: option.role }) + } else if (option.type) { + submenu.push({ type: option.type }) + } else { + submenu.push({ label: option.name, accelerator: option.accelerator, click: option.downfn }) + } + } + injection.push({ label: cat, submenu: submenu }) + } + app.injectMenu(injection) + } +} diff --git a/desktop/sources/scripts/lib/controller.js b/desktop/sources/scripts/lib/controller.js deleted file mode 100644 index 6b81027..0000000 --- a/desktop/sources/scripts/lib/controller.js +++ /dev/null @@ -1,81 +0,0 @@ -'use strict' - -export default function Controller () { - this.menu = { default: {} } - this.mode = 'default' - this.app = require('electron').remote.app - - this.start = function () { - } - - this.add = function (mode, cat, label, fn, accelerator) { - if (!this.menu[mode]) { this.menu[mode] = {} } - if (!this.menu[mode][cat]) { this.menu[mode][cat] = {} } - this.menu[mode][cat][label] = { - fn: function (_menuItem, browserWindow) { - browserWindow.webContents.focus() - fn.apply(this, arguments) - }, - accelerator: accelerator - } - } - - this.addRole = function (mode, cat, label) { - if (!this.menu[mode]) { this.menu[mode] = {} } - if (!this.menu[mode][cat]) { this.menu[mode][cat] = {} } - this.menu[mode][cat][label] = { role: label } - } - - this.addSpacer = function (mode, cat, label, type = 'separator') { - if (!this.menu[mode]) { this.menu[mode] = {} } - if (!this.menu[mode][cat]) { this.menu[mode][cat] = {} } - this.menu[mode][cat][label] = { type: type } - } - - this.clearCat = function (mode, cat) { - if (this.menu[mode]) { this.menu[mode][cat] = {} } - } - - this.set = function (mode = 'default') { - this.mode = mode - this.commit() - } - - this.format = function () { - const f = [] - const m = this.menu[this.mode] - for (const cat in m) { - const submenu = [] - for (const name in m[cat]) { - const option = m[cat][name] - if (option.role) { - submenu.push({ role: option.role }) - } else if (option.type) { - submenu.push({ type: option.type }) - } else { - submenu.push({ label: name, accelerator: option.accelerator, click: option.fn }) - } - } - f.push({ label: cat, submenu: submenu }) - } - return f - } - - this.commit = function () { - console.log('Controller', 'Changing..') - this.app.injectMenu(this.format()) - } - - this.accelerator = function (key, menu) { - const acc = { basic: null, ctrl: null } - for (const cat in menu) { - const options = menu[cat] - for (const id in options.submenu) { - const option = options.submenu[id]; if (option.role) { continue } - acc.basic = (option.accelerator.toLowerCase() === key.toLowerCase()) ? option.label.toUpperCase().replace('TOGGLE ', '').substr(0, 8).trim() : acc.basic - acc.ctrl = (option.accelerator.toLowerCase() === ('CmdOrCtrl+' + key).toLowerCase()) ? option.label.toUpperCase().replace('TOGGLE ', '').substr(0, 8).trim() : acc.ctrl - } - } - return acc - } -} diff --git a/desktop/sources/scripts/lib/history.js b/desktop/sources/scripts/lib/history.js new file mode 100644 index 0000000..1bbf0ae --- /dev/null +++ b/desktop/sources/scripts/lib/history.js @@ -0,0 +1,74 @@ +'use strict' + +function History () { + this.index = 0 + this.frames = [] + this.host = null + this.key = null + + this.bind = function (host, key) { + console.log('History is recording..') + this.host = host + this.key = key + this.reset() + } + + this.reset = function () { + this.index = 0 + this.frames = [] + } + + this.record = function (data) { + if (this.index === this.frames.length) { + this.append(data) + } else { + this.fork(data) + } + this.trim() + this.index = this.frames.length + } + + this.undo = function () { + if (this.index === 0) { console.warn('History', 'Reached beginning'); return } + this.index = clamp(this.index - 1, 0, this.frames.length - 2) + this.apply(this.frames[this.index]) + } + + this.redo = function () { + if (this.index + 1 > this.frames.length - 1) { console.warn('History', 'Reached end'); return } + this.index = clamp(this.index + 1, 0, this.frames.length - 1) + this.apply(this.frames[this.index]) + } + + this.apply = function (f) { + if (!this.host[this.key]) { console.log(`Unknown binding to key ${this.key}`); return } + if (!f || f.length !== this.host[this.key].length) { return } + this.host[this.key] = this.frames[this.index] + } + + this.append = function (data) { + if (!data) { return } + if (this.frames[this.index - 1] && this.frames[this.index - 1] === data) { return } + this.frames.push(data) + } + + this.fork = function (data) { + this.frames = this.frames.slice(0, this.index + 1) + this.append(data) + } + + this.trim = function (limit = 30) { + if (this.frames.length < limit) { return } + this.frames.shift() + } + + this.last = function () { + return this.frames[this.index - 1] + } + + this.length = function () { + return this.frames.length + } + + function clamp (v, min, max) { return v < min ? min : v > max ? max : v } +} diff --git a/desktop/sources/scripts/lib/theme.js b/desktop/sources/scripts/lib/theme.js index a2777fe..94061ed 100644 --- a/desktop/sources/scripts/lib/theme.js +++ b/desktop/sources/scripts/lib/theme.js @@ -1,20 +1,25 @@ 'use strict' -export default function Theme (_default) { - const fs = require('fs') - const url = require('url') +/* global localStorage */ +/* global FileReader */ +/* global DOMParser */ - this.active = _default +function Theme () { + const themer = this + + this.default = { background: '#eee', f_high: '#000', f_med: '#999', f_low: '#ccc', f_inv: '#000', b_high: '#000', b_med: '#888', b_low: '#aaa', b_inv: '#ffb545' } + this.active = {} this.el = document.createElement('style') this.el.type = 'text/css' - this.install = function (host = document.body, callback) { + this.install = (host = document.body, callback) => { host.appendChild(this.el) this.callback = callback } - this.start = function () { + this.start = () => { + this.active = this.default console.log('Theme', 'Starting..') if (isJson(localStorage.theme)) { const storage = JSON.parse(localStorage.theme) @@ -24,12 +29,12 @@ export default function Theme (_default) { return } } - this.load(_default) + this.load(this.active) } - this.load = function (data) { + this.load = (data) => { const theme = parse(data) - if (!validate(theme)) { console.warn('Theme', 'Not a theme', theme); return } + if (!validate(theme)) { return } console.log('Theme', 'Loaded theme!') this.el.innerHTML = `:root { --background: ${theme.background}; --f_high: ${theme.f_high}; --f_med: ${theme.f_med}; --f_low: ${theme.f_low}; --f_inv: ${theme.f_inv}; --b_high: ${theme.b_high}; --b_med: ${theme.b_med}; --b_low: ${theme.b_low}; --b_inv: ${theme.b_inv}; }` localStorage.setItem('theme', JSON.stringify(theme)) @@ -39,18 +44,12 @@ export default function Theme (_default) { } } - this.reset = function () { - this.load(_default) - } - - this.setImage = function (path) { - document.body.style.backgroundImage = path && fs.existsSync(path) && document.body.style.backgroundImage !== `url(${url.pathToFileURL(path)})` ? `url(${url.pathToFileURL(path)})` : '' + this.reset = () => { + this.load(this.default) } - this.set = function (key, value) { - if (!this.active[key]) { console.warn('Theme', 'Unknown key ' + key); return } - if (!isColor(value)) { console.warn('Theme', 'Not a color ' + value); return } - this.active[key] = '#' + value + this.get = (key) => { + return this.active[key] } function parse (any) { @@ -60,7 +59,7 @@ export default function Theme (_default) { // Drag - this.drag = function (e) { + this.drag = (e) => { e.stopPropagation() e.preventDefault() e.dataTransfer.dropEffect = 'copy' @@ -71,10 +70,10 @@ export default function Theme (_default) { e.stopPropagation() const file = e.dataTransfer.files[0] if (!file || !file.name) { console.warn('Theme', 'Unnamed file.'); return } - if (file.name.indexOf('.thm') < 0 && file.name.indexOf('.svg') < 0) { console.warn('Theme', 'Skipped, not a theme'); return } + if (file.name.indexOf('.thm') < 0 && file.name.indexOf('.svg') < 0) { return } const reader = new FileReader() - reader.onload = (e) => { - this.load(e.target.result) + reader.onload = function (e) { + themer.load(e.target.result) } reader.readAsText(file) } @@ -82,11 +81,12 @@ export default function Theme (_default) { this.open = () => { const fs = require('fs') const { dialog, app } = require('electron').remote - const paths = dialog.showOpenDialogSync(app.win, { properties: ['openFile'], filters: [{ name: 'Themes', extensions: ['svg'] }] }) + const paths = dialog.showOpenDialog(app.win, { properties: ['openFile'], filters: [{ name: 'Themes', extensions: ['svg'] }] }) if (!paths) { console.log('Nothing to load'); return } - const data = fs.readFileSync(paths[0], 'utf8') - if (!data) { return } - this.load(data) + fs.readFile(paths[0], 'utf8', function (err, data) { + if (err) throw err + themer.load(data) + }) } window.addEventListener('dragover', this.drag) @@ -131,10 +131,6 @@ export default function Theme (_default) { try { JSON.parse(text); return true } catch (error) { return false } } - function isColor (str) { - return /(^#[0-9A-F]{6}$)|(^#[0-9A-F]{3}$)/i.test('#' + str) - } - function isHtml (text) { try { new DOMParser().parseFromString(text, 'text/xml'); return true } catch (error) { return false } } |