From 536da7acbf98b78f7510387317e5addfcc944afd Mon Sep 17 00:00:00 2001 From: Stewart Allen Date: Tue, 18 Jan 2022 16:34:42 -0500 Subject: [PATCH] add prefs dialog, dark mode --- src/main/mesh.js | 38 +++++++++++++++++++++++++++++++++++--- src/mesh/api.js | 18 +++++++++++++----- src/mesh/build.js | 20 ++++++++++++++++++-- src/mesh/util.js | 2 +- src/moto/space.js | 10 +++++----- web/mesh/index.css | 22 +++++++++++++++------- 6 files changed, 87 insertions(+), 23 deletions(-) diff --git a/src/main/mesh.js b/src/main/mesh.js index 9c3c02de..37ab58d3 100644 --- a/src/main/mesh.js +++ b/src/main/mesh.js @@ -112,7 +112,7 @@ function restore_space() { store_matrices(); }).then(() => { // restore preferences after models are restored - api.prefs.load().then(() => { + return api.prefs.load().then(() => { let { map } = api.prefs; let { space, mode } = map; api.grid(space.grid); @@ -123,10 +123,13 @@ function restore_space() { api.selection.set([...smodel, ...sgroup]); // restore edit mode api.mode.set(mode); + // restore dark mode + set_darkmode(map.space.dark); }); + }).finally(() => { + // hide loading curtain + $d('curtain','none'); }); - // hide loading curtain - $d('curtain','none'); } // toggle edit/split temporary mode (present plane on hover) @@ -254,8 +257,13 @@ function space_init(data) { if (api.modal.showing) { return; } + if (evt.key === '?') { + return api.help(); + } let { shiftKey, metaKey, ctrlKey, code } = evt; switch (code) { + case 'KeyQ': + return api.settings(); case 'KeyI': return api.file.import(); case 'KeyX': @@ -454,6 +462,29 @@ function object_destroy(id) { store_matrices(); } +// listen for changes like dark mode toggle +function set_darkmode(dark) { + let { prefs } = mesh.api; + let { sky, platform } = moto.Space; + if (dark) { + mesh.material.wireframe.color.set(0xeeeeee); + } else { + mesh.material.wireframe.color.set(0,0,0); + } + sky.set({ color: dark ? 0 : 0xffffff }); + platform.set({ + grid: dark ? { + colorMajor: 0x666666, + colorMinor: 0x333333, + } : { + colorMajor: 0xcccccc, + colorMinor: 0xeeeeee, + }, + }); + prefs.map.space.dark = dark; + prefs.save(); +} + // bind functions to topics broker.listeners({ load_files, @@ -461,6 +492,7 @@ broker.listeners({ space_load, object_matrix, object_destroy, + set_darkmode, edit_split }); diff --git a/src/mesh/api.js b/src/mesh/api.js index d6d3550e..8d988ba8 100644 --- a/src/mesh/api.js +++ b/src/mesh/api.js @@ -420,6 +420,10 @@ let mode = { }, }; +// cache pref signature so we know when it changes +let prefsig; +let prefsignew; + // persisted preference map let prefs = { map: { @@ -433,14 +437,18 @@ let prefs = { }, }, - put(key, val) { - prefs.map[key] = val; - prefs.update(); + // look for changes in pref signature + changed() { + prefsignew = JSON.stringify(prefs.map); + return prefsignew !== prefsig; }, // persist to data store save() { - mesh.db.admin.put("prefs", prefs.map); + if (prefs.changed()) { + mesh.db.admin.put("prefs", prefs.map); + prefsig = prefsignew; + } }, // reload from data store @@ -546,6 +554,6 @@ broker.wrapObject(model, 'model'); broker.wrapObject(group, 'group'); // optimize db writes by merging updates -prefs.save = util.deferWrap(prefs.save); +prefs.save = util.deferWrap(prefs.save, 100); })(); diff --git a/src/mesh/build.js b/src/mesh/build.js index e895d85a..704f2378 100644 --- a/src/mesh/build.js +++ b/src/mesh/build.js @@ -169,6 +169,18 @@ let log = api.log = { // bind endpoint for worker to log in the ui gapp.broker.subscribe("mesh.log", log.emit); +// bind settings endpoint to api +api.settings = function() { + modal.show('settings', h.div([ + h.label('dark mode'), + h.input({ + type: "checkbox", + onchange: ev => call.set_darkmode(ev.target.checked), + [ api.prefs.map.space.dark ? 'checked' : 'unchecked' ] : 1 + }) + ])); +} + // create html elements function ui_build() { // set app version @@ -177,8 +189,12 @@ function ui_build() { // add a help button h.bind($('top-right'), [ - h.div({ id: "help", onclick: api.help }, - [ h.div({ class: "far fa-question-circle" }) ]) + h.div({ id: "top-settings", onclick: api.settings }, [ + h.div({ class: "fas fa-sliders-h" }), + ]), + h.div({ id: "top-help", onclick: api.help }, [ + h.div({ class: "far fa-question-circle" }), + ]), ]); // create top level app areas diff --git a/src/mesh/util.js b/src/mesh/util.js index 98db5a4c..13abf41a 100644 --- a/src/mesh/util.js +++ b/src/mesh/util.js @@ -50,7 +50,7 @@ let util = mesh.util = { rec.timer = setTimeout(() => { deferFn.remove(rec); fn(); - }); + }, time); deferFn.push(rec); }, diff --git a/src/moto/space.js b/src/moto/space.js index 6a359fa4..9110a981 100644 --- a/src/moto/space.js +++ b/src/moto/space.js @@ -458,8 +458,8 @@ } function setGridColor(opt = {}) { - grid.colorMajor = valueOr(opt.major, grid.colorMajor); - grid.colorMinor = valueOr(opt.minor, grid.colorMinor); + grid.colorMajor = valueOr(opt.major || opt.colorMajor, grid.colorMajor); + grid.colorMinor = valueOr(opt.minor || opt.colorMinor, grid.colorMinor); grid.colorX = valueOr(opt.colorX, grid.colorX); grid.colorY = valueOr(opt.colorY, grid.colorY); updateGrid(); @@ -921,8 +921,8 @@ function setSky(opt = {}) { let { grid, color, gridColor } = opt; if (grid) Space.sky.showGrid(grid); - if (color) Space.sky.setColor(color); - if (gridColor) Space.sky.setGridColor(gridColor); + if (color !== undefined) Space.sky.setColor(color); + if (gridColor !== undefined) Space.sky.setGridColor(gridColor); } function setPlatform(opt = {}) { @@ -945,7 +945,7 @@ let { colorX, colorY, colorMajor, colorMinor } = grid; platform.setGrid(major, minor); platform.setGridColor({ colorX, colorY, colorMajor, colorMinor }); - platform.setGridZOff(zOffset); + if (zOffset !== undefined) platform.setGridZOff(zOffset); } if (origin) { let { x, y, z, show } = origin; diff --git a/web/mesh/index.css b/web/mesh/index.css index e7bf291c..40a468ec 100644 --- a/web/mesh/index.css +++ b/web/mesh/index.css @@ -109,7 +109,7 @@ body, div { padding: 3px 0 3px 0; flex-direction: row; font-family: 'Russo One', sans-serif; - background-color: rgba(255,255,255,0.75); + background-color: rgba(255,255,255,0.55); } #top-sep { @@ -168,20 +168,26 @@ button:hover { position: absolute; padding: 3px; bottom: 0; - right: 0; + right: 3px; top: 0; + gap: 5px; } -#help { +#top-right > div { + flex-direction: row; + color: #888; +} + +#top-right > div:hover { + color: black; +} + +#top-settings, #top-help { flex-direction: column; justify-content: center; align-items: center } -#help:hover { - color: #888; -} - .export { flex-direction: column; font-family: monospace; @@ -236,6 +242,8 @@ button:hover { border-top-right-radius: 4px; border-bottom: 1px solid gray; background-color: rgba(0,0,0,0.2); + font-family: 'Russo One', monospace; + font-size: smaller; justify-content: center; align-items: center; }