add prefs dialog, dark mode

This commit is contained in:
Stewart Allen 2022-01-18 16:34:42 -05:00
commit 536da7acbf
6 changed files with 87 additions and 23 deletions

View file

@ -112,7 +112,7 @@ function restore_space() {
store_matrices(); store_matrices();
}).then(() => { }).then(() => {
// restore preferences after models are restored // restore preferences after models are restored
api.prefs.load().then(() => { return api.prefs.load().then(() => {
let { map } = api.prefs; let { map } = api.prefs;
let { space, mode } = map; let { space, mode } = map;
api.grid(space.grid); api.grid(space.grid);
@ -123,10 +123,13 @@ function restore_space() {
api.selection.set([...smodel, ...sgroup]); api.selection.set([...smodel, ...sgroup]);
// restore edit mode // restore edit mode
api.mode.set(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) // toggle edit/split temporary mode (present plane on hover)
@ -254,8 +257,13 @@ function space_init(data) {
if (api.modal.showing) { if (api.modal.showing) {
return; return;
} }
if (evt.key === '?') {
return api.help();
}
let { shiftKey, metaKey, ctrlKey, code } = evt; let { shiftKey, metaKey, ctrlKey, code } = evt;
switch (code) { switch (code) {
case 'KeyQ':
return api.settings();
case 'KeyI': case 'KeyI':
return api.file.import(); return api.file.import();
case 'KeyX': case 'KeyX':
@ -454,6 +462,29 @@ function object_destroy(id) {
store_matrices(); 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 // bind functions to topics
broker.listeners({ broker.listeners({
load_files, load_files,
@ -461,6 +492,7 @@ broker.listeners({
space_load, space_load,
object_matrix, object_matrix,
object_destroy, object_destroy,
set_darkmode,
edit_split edit_split
}); });

View file

@ -420,6 +420,10 @@ let mode = {
}, },
}; };
// cache pref signature so we know when it changes
let prefsig;
let prefsignew;
// persisted preference map // persisted preference map
let prefs = { let prefs = {
map: { map: {
@ -433,14 +437,18 @@ let prefs = {
}, },
}, },
put(key, val) { // look for changes in pref signature
prefs.map[key] = val; changed() {
prefs.update(); prefsignew = JSON.stringify(prefs.map);
return prefsignew !== prefsig;
}, },
// persist to data store // persist to data store
save() { save() {
mesh.db.admin.put("prefs", prefs.map); if (prefs.changed()) {
mesh.db.admin.put("prefs", prefs.map);
prefsig = prefsignew;
}
}, },
// reload from data store // reload from data store
@ -546,6 +554,6 @@ broker.wrapObject(model, 'model');
broker.wrapObject(group, 'group'); broker.wrapObject(group, 'group');
// optimize db writes by merging updates // optimize db writes by merging updates
prefs.save = util.deferWrap(prefs.save); prefs.save = util.deferWrap(prefs.save, 100);
})(); })();

View file

@ -169,6 +169,18 @@ let log = api.log = {
// bind endpoint for worker to log in the ui // bind endpoint for worker to log in the ui
gapp.broker.subscribe("mesh.log", log.emit); 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 // create html elements
function ui_build() { function ui_build() {
// set app version // set app version
@ -177,8 +189,12 @@ function ui_build() {
// add a help button // add a help button
h.bind($('top-right'), [ h.bind($('top-right'), [
h.div({ id: "help", onclick: api.help }, h.div({ id: "top-settings", onclick: api.settings }, [
[ h.div({ class: "far fa-question-circle" }) ]) 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 // create top level app areas

View file

@ -50,7 +50,7 @@ let util = mesh.util = {
rec.timer = setTimeout(() => { rec.timer = setTimeout(() => {
deferFn.remove(rec); deferFn.remove(rec);
fn(); fn();
}); }, time);
deferFn.push(rec); deferFn.push(rec);
}, },

View file

@ -458,8 +458,8 @@
} }
function setGridColor(opt = {}) { function setGridColor(opt = {}) {
grid.colorMajor = valueOr(opt.major, grid.colorMajor); grid.colorMajor = valueOr(opt.major || opt.colorMajor, grid.colorMajor);
grid.colorMinor = valueOr(opt.minor, grid.colorMinor); grid.colorMinor = valueOr(opt.minor || opt.colorMinor, grid.colorMinor);
grid.colorX = valueOr(opt.colorX, grid.colorX); grid.colorX = valueOr(opt.colorX, grid.colorX);
grid.colorY = valueOr(opt.colorY, grid.colorY); grid.colorY = valueOr(opt.colorY, grid.colorY);
updateGrid(); updateGrid();
@ -921,8 +921,8 @@
function setSky(opt = {}) { function setSky(opt = {}) {
let { grid, color, gridColor } = opt; let { grid, color, gridColor } = opt;
if (grid) Space.sky.showGrid(grid); if (grid) Space.sky.showGrid(grid);
if (color) Space.sky.setColor(color); if (color !== undefined) Space.sky.setColor(color);
if (gridColor) Space.sky.setGridColor(gridColor); if (gridColor !== undefined) Space.sky.setGridColor(gridColor);
} }
function setPlatform(opt = {}) { function setPlatform(opt = {}) {
@ -945,7 +945,7 @@
let { colorX, colorY, colorMajor, colorMinor } = grid; let { colorX, colorY, colorMajor, colorMinor } = grid;
platform.setGrid(major, minor); platform.setGrid(major, minor);
platform.setGridColor({ colorX, colorY, colorMajor, colorMinor }); platform.setGridColor({ colorX, colorY, colorMajor, colorMinor });
platform.setGridZOff(zOffset); if (zOffset !== undefined) platform.setGridZOff(zOffset);
} }
if (origin) { if (origin) {
let { x, y, z, show } = origin; let { x, y, z, show } = origin;

View file

@ -109,7 +109,7 @@ body, div {
padding: 3px 0 3px 0; padding: 3px 0 3px 0;
flex-direction: row; flex-direction: row;
font-family: 'Russo One', sans-serif; font-family: 'Russo One', sans-serif;
background-color: rgba(255,255,255,0.75); background-color: rgba(255,255,255,0.55);
} }
#top-sep { #top-sep {
@ -168,20 +168,26 @@ button:hover {
position: absolute; position: absolute;
padding: 3px; padding: 3px;
bottom: 0; bottom: 0;
right: 0; right: 3px;
top: 0; 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; flex-direction: column;
justify-content: center; justify-content: center;
align-items: center align-items: center
} }
#help:hover {
color: #888;
}
.export { .export {
flex-direction: column; flex-direction: column;
font-family: monospace; font-family: monospace;
@ -236,6 +242,8 @@ button:hover {
border-top-right-radius: 4px; border-top-right-radius: 4px;
border-bottom: 1px solid gray; border-bottom: 1px solid gray;
background-color: rgba(0,0,0,0.2); background-color: rgba(0,0,0,0.2);
font-family: 'Russo One', monospace;
font-size: smaller;
justify-content: center; justify-content: center;
align-items: center; align-items: center;
} }