diff --git a/main.js b/main.js index e4a149f..7e4d32d 100644 --- a/main.js +++ b/main.js @@ -70,7 +70,9 @@ const defaultSettings = { cors: true, dirs: true, index: true, + recent: [], }; +const maxRecent = 10; let settings; try { @@ -219,6 +221,7 @@ function startServer() { expressApp.use(serveIndex(root, { icons: true, stylesheet: path.join(__dirname, "src", "listing.css"), + template: path.join(__dirname, "src", "listing.html"), })); } expressApp.use(nonErrorLocalErrorHandler); @@ -236,6 +239,7 @@ function startServer() { saveSettings(); } sendToWindow('started'); + sendToWindow('settings', settings); logToWindow("server started on port:", local ? "127.0.0.1:" : "::", port, "for path:", root); }); server.on('close', serverClosed); @@ -258,6 +262,13 @@ function stopServer() { function saveSettings() { try { + // remove root from recent + settings.recent = settings.recent.filter(v => v !== settings.root); + // add root to recent + settings.recent.unshift(settings.root); + // remove excess + settings.recent.splice(maxRecent, settings.length - maxRecent); + fs.writeFileSync(settingsPath, JSON.stringify(settings, null, 2)); } catch (e) { errorToWindow('ERROR: could not save settings:', e); @@ -265,8 +276,17 @@ function saveSettings() { } function updateSettings(event, newSettings) { - Object.assign(settings, newSettings); - if (running) { + let changed = false; + // this is horrible but for now it works + for (const key of Object.keys(newSettings)) { + const newValue = newSettings[key]; + const oldValue = settings[key]; + if (!Array.isArray(oldValue) && oldValue !== newValue) { + changed = true; + settings[key] = newValue; + } + } + if (changed && running) { startServer(); } } diff --git a/src/index.html b/src/index.html index 4f21bc7..0330bab 100644 --- a/src/index.html +++ b/src/index.html @@ -10,6 +10,10 @@

A simple web server for local web development

+
diff --git a/src/index.js b/src/index.js index 3733fd9..bd4dca0 100644 --- a/src/index.js +++ b/src/index.js @@ -103,19 +103,56 @@ ipcRenderer.on('stopped', () => { ipcRenderer.send('getSettings'); function removeClass(elem, className) { - const classNames = elem.className.split(" "); - let ndx; - while ((ndx = classNames.indexOf(className)) >= 0) { - classNames.splice(ndx, 1); - } - elem.className = classNames.join(" "); + elem.classList.remove(className); } function addClass(elem, className) { - const classNames = elem.className.split(" "); - if (classNames.indexOf(className) < 0) { - classNames.push(className); - elem.className = classNames.join(" "); + elem.classList.add(className); +} + +class Dropdown { + constructor(elem, callback) { + this.toggle = this.toggle.bind(this); + this.hide = this.hide.bind(this); + this.callback = callback; + this.elem = elem; + this.buttonElem = elem.querySelector('button'); + this.contentElem = elem.querySelector('div'); + this.buttonElem.addEventListener('click', this.toggle); + document.addEventListener('click', (e) => { + const isClickInside = this.buttonElem.contains(event.target); + if (!isClickInside) { + this.hide(); + } + }); + } + toggle() { + const style = this.contentElem.style; + const show = !!style.display; + style.display = show ? '' : 'block'; + if (show) { + this.contentElem.focus(); + } + } + hide() { + const style = this.contentElem.style; + const show = !!style.display; + if (show) { + this.toggle(); + } + } + setOptions(options) { + this.contentElem.innerHTML = ''; + options.forEach((option, ndx) => { + const div = document.createElement('div'); + div.textContent = option; + div.addEventListener('click', () => { + this.hide(); + this.callback(option); + }); + this.contentElem.appendChild(div); + }); + this.elem.style.display = options.length ? '' : 'none'; } } @@ -161,6 +198,20 @@ async function getFolderToServe() { } } +const recent = new Dropdown($('#recent'), (newPath) => { + rootElem.value = newPath; + updateSettings(); +}); + +settingsInfo.recent = { + set: settings => { + recent.setOptions(settings.recent); + }, + get: settings => { + return settings.recent = settingsInfo.recent; + }, +}; + browseRootElem.addEventListener('click', e => { getFolderToServe(); }); diff --git a/src/listing.html b/src/listing.html new file mode 100644 index 0000000..05b5d04 --- /dev/null +++ b/src/listing.html @@ -0,0 +1,82 @@ + + + + + + listing directory {directory} + + + + + +
+

~{linked-path}

+ {files} +
+ + \ No newline at end of file diff --git a/src/style.css b/src/style.css index 16fb339..9298a92 100644 --- a/src/style.css +++ b/src/style.css @@ -57,8 +57,38 @@ input { .checkbox label { order: 2; } + +.icon { + +} +.dropdown { + position: relative; + display: inline-block; +} + +.dropdown>div { + display: none; + position: absolute; + right: 0; + background-color: #DDD; + color: black; + min-width: 250px; + z-index: 1; + border: 1px solid #444; +} +.dropdown>div>div { + padding: .1em; + white-space: pre; +} +.dropdown>div>div:nth-child(odd) { + background-color: #CCC; +} +.dropdown>div>div:hover { + background-color: #888; +} + .buttons { - padding-top: 1em; + padding-top: s1em; } .buttons button { font-size: large;