From c4cc2170f50cb76f84c95c553f8b920b487e293b Mon Sep 17 00:00:00 2001 From: Daniel Stock Date: Mon, 3 Jun 2024 16:32:05 +0200 Subject: [PATCH] config file loading and saving --- config.example.json | 2 +- html/config.html | 29 +++++----- html/onboarding.html | 2 +- js/config.js | 4 +- js/configPreload.js | 7 +++ js/configRenderer.js | 35 +++++++++++++ main.js | 122 +++++++++++++++++++++++++++++++------------ 7 files changed, 149 insertions(+), 52 deletions(-) create mode 100644 js/configPreload.js create mode 100644 js/configRenderer.js diff --git a/config.example.json b/config.example.json index 4649d2e..5bbd787 100644 --- a/config.example.json +++ b/config.example.json @@ -1,6 +1,6 @@ { "url": "file:///assets/data/index.html", - "allowedDomains": [ + "whitelist": [ "localhost", "127.0.0.1", "tooloop.de", diff --git a/html/config.html b/html/config.html index a8463b5..3fcc1df 100644 --- a/html/config.html +++ b/html/config.html @@ -15,12 +15,6 @@ padding: 1rem; } - h1 { - font-weight: 500; - font-size: 1.333rem; - margin-bottom: 2em; - } - label { color: #ccc; text-align: right; @@ -36,7 +30,7 @@ border-radius: 0.25rem; background-color: rgba(255, 255, 255, 0.05); } - + input, textarea { font-family: monospace; @@ -46,19 +40,23 @@ border: 1px solid rgba(255, 255, 255, 0.12); border-radius: 0.25rem; } - + + textarea#whitelist { + height: 5.25em; + } + textarea:focus, input:focus { outline: none; } - + .buttons { grid-column: 2; display: flex; gap: 1rem; margin-top: 2rem; } - + button { background-color: hsl(0, 0%, 50%); /* border: 1px solid rgba(255, 255, 255, 0.12); */ @@ -72,7 +70,6 @@ -

Config

@@ -80,14 +77,16 @@ - - + +
- - + +
+ + \ No newline at end of file diff --git a/html/onboarding.html b/html/onboarding.html index 4dcb026..6c7e616 100644 --- a/html/onboarding.html +++ b/html/onboarding.html @@ -165,7 +165,7 @@

{
     "url": "https://www.tooloop.de",
-    "allowedDomains": [
+    "whitelist": [
         "tooloop.de",
         "www.tooloop.de"
     ],
diff --git a/js/config.js b/js/config.js
index 0a22564..e68aa13 100644
--- a/js/config.js
+++ b/js/config.js
@@ -3,7 +3,7 @@ class Config {
     constructor() {
         this.config = {
             "url": "https://www.tooloop.de",
-            "allowedDomains": [
+            "whitelist": [
                 "tooloop.de",
                 "www.tooloop.de"
             ],
@@ -15,7 +15,7 @@ class Config {
 
 let config = {
     "url": "https://www.tooloop.de",
-    "allowedDomains": [
+    "whitelist": [
         "tooloop.de",
         "www.tooloop.de"
     ],
diff --git a/js/configPreload.js b/js/configPreload.js
new file mode 100644
index 0000000..ae5359d
--- /dev/null
+++ b/js/configPreload.js
@@ -0,0 +1,7 @@
+const { contextBridge, ipcRenderer } = require('electron/renderer')
+
+contextBridge.exposeInMainWorld('electronAPI', {
+    save: (configData) => ipcRenderer.send('save-config', configData),
+    cancel: () => ipcRenderer.send('cancel-config'),
+    onUpdate: (callback) => ipcRenderer.on('update-config', (_event, configData) => callback(configData))
+});
\ No newline at end of file
diff --git a/js/configRenderer.js b/js/configRenderer.js
new file mode 100644
index 0000000..f6e84f1
--- /dev/null
+++ b/js/configRenderer.js
@@ -0,0 +1,35 @@
+const urlField = document.getElementById('url');
+const whitelistField = document.getElementById('whitelist');
+const logPathField = document.getElementById('logpath');
+const saveButton = document.getElementById('save');
+const cancelButton = document.getElementById('cancel');
+
+saveButton.addEventListener('click', () => {
+    let configData = {
+        url: "",
+        whitelist: [],
+        logPath: "",
+    };
+
+    configData.url = urlField.value;
+    configData.logPath = logPathField.value;
+    configData.whitelist = whitelistField.value;
+
+    window.electronAPI.save(configData);
+})
+
+cancelButton.addEventListener('click', () => { window.electronAPI.cancel() });
+
+window.electronAPI.onUpdate((configData) => {
+    urlField.value = configData.url;
+    let whitelist = "";
+    configData.whitelist.forEach(item => {
+        whitelist += item + ";\n";
+    });
+    whitelistField.value = whitelist;
+    logPathField.value = configData.logPath;
+});
+
+document.addEventListener('keyup', (event) => {
+    if (event.code == 'Escape') window.electronAPI.cancel();
+});
\ No newline at end of file
diff --git a/main.js b/main.js
index 00e4b62..cfd27ac 100644
--- a/main.js
+++ b/main.js
@@ -1,4 +1,4 @@
-const { app, BrowserWindow, BaseWindow, nativeTheme, Menu, MenuItem } = require('electron/main');
+const { app, BrowserWindow, ipcMain, nativeTheme, Menu, MenuItem } = require('electron/main');
 const path = require('node:path');
 const fs = require('fs');
 const os = require('os');
@@ -14,6 +14,7 @@ const isMac = process.platform === 'darwin';
 //------------------------------------------------------------------------------
 
 let config;
+let configPath;
 let configWindow;
 let win;
 let menu;
@@ -40,28 +41,104 @@ function loadConfig() {
         __dirname
     ];
 
-    let filePath;
-
     // Check all locations
     for (const location of locations) {
         // Update the filepath
-        filePath = path.join(location, 'config.json');
+        configPath = path.join(location, 'config.json');
         try {
             // Try access
-            fs.accessSync(filePath);
+            fs.accessSync(configPath);
 
             // Parse the file if found
-            console.info('Found config file at ' + filePath);
-            const data = fs.readFileSync(filePath, { encoding: 'utf8' });
+            console.info('Found config file at ' + configPath);
+            const data = fs.readFileSync(configPath, { encoding: 'utf8' });
             config = JSON.parse(data);
 
             // Break the loop
             break;
         } catch (err) {
-            console.warn('No config file found at ' + filePath);
+            console.warn('No config file found at ' + configPath);
         }
     }
+}
 
+function saveConfig(newConfig) {
+    if (!configPath) {
+        console.error("No config file path was set");
+        return;
+    }
+
+
+    if(config.url != newConfig.url) {
+        config.url = newConfig.url;
+        loadUrlAsync(config.url);
+    }
+    
+    config.whitelist = [];
+    let whitelist = newConfig.whitelist.split(";");
+    whitelist = whitelist.filter(function (entry) { return entry.trim() != ''; });
+    whitelist.forEach(
+        token => {
+            config.whitelist.push(token.replace(/\r?\n|\r/g, ""));
+        }
+    );
+    
+
+    config.logPath = newConfig.logPath;
+
+    fs.writeFile(configPath, JSON.stringify(config, null, "  "), (error) => {
+        if (error) log.warn('Error writing to ' + configPath, error);
+        log.info("Saved config to " + configPath);
+    });
+
+    // updare UI with new values
+    configWindow.webContents.send('update-config', config);
+}
+
+
+/**
+ * Creates a modal config view and attaches as to the main window
+ */
+function showConfigWindow() {
+    // create lazily
+    if (configWindow == undefined) {
+        configWindow = new BrowserWindow({
+            parent: win,
+            width: 640,
+            height: 460,
+            minimizable: false,
+            maximizable: false,
+            fullscreenable: false,
+            backgroundColor: '#1f1f1f',
+            autoHideMenuBar: true,
+            excludedFromShownWindowsMenu: true,
+            webPreferences: {
+                preload: path.join(__dirname, 'js/configPreload.js')
+            }
+        });
+
+        configWindow.on('close', (event) => {
+            event.preventDefault();
+            configWindow.hide();
+        });
+
+        ipcMain.on('save-config', (event, configData) => {
+            configWindow.hide();
+            saveConfig(configData);
+        });
+        ipcMain.on('cancel-config', (event) => {
+            configWindow.hide();
+            configWindow.webContents.send('update-config', config);
+        });
+
+        configWindow.loadFile('./html/config.html');
+    }
+
+    // update text field values
+    configWindow.webContents.send('update-config', config);
+
+    // show window
+    configWindow.show();
 }
 
 
@@ -75,8 +152,9 @@ function createMainWindow() {
         backgroundColor: '#000000',
         icon: 'images/icon-512.png',
         autoHideMenuBar: true,
+        kiosk: true,
         webPreferences: {
-            preload: path.join(__dirname, './js/preload.js'),
+            preload: path.join(__dirname, 'js/preload.js'),
             webSecurity: false,
             disableDialogs: true
         },
@@ -99,11 +177,6 @@ function createMainWindow() {
     });
     win.on("page-title-updated", (event) => event.preventDefault());
 
-
-    // show initial black window
-    // win.setKiosk(true);
-    win.show();
-
     // Load page from config file
     if (config != undefined && 'url' in config) {
         loadUrlAsync(config.url);
@@ -119,22 +192,6 @@ function createMainWindow() {
     }
 }
 
-/**
- * Creates a modal config view and attaches as to the main window
- */
-function createConfigWindow() {
-    configWindow = new BrowserWindow({
-        parent: win,
-        modal: true,
-        width: 640,
-        height: 460,
-        show: false,
-        backgroundColor: '#1f1f1f'
-    });
-
-    configWindow.loadFile('./html/config.html');
-}
-
 
 /**
  * Creates all available keyboard shortcuts
@@ -155,7 +212,7 @@ function createMenu() {
             {
                 label: 'Config',
                 accelerator: isMac ? 'Cmd+,' : 'Ctrl+,',
-                click: () => { configWindow.isVisible() ? configWindow.hide() : configWindow.show(); }
+                click: () => { showConfigWindow(); }
             }
         ]
     }));
@@ -178,7 +235,7 @@ function validateDomain(event) {
     // allow local urls
     if (['file:', 'file'].includes(url.protocol)) return true;
 
-    if ('allowedDomains' in config && !config.allowedDomains.includes(url.hostname)) {
+    if ('whitelist' in config && !config.whitelist.includes(url.hostname)) {
         event.preventDefault();
         log.info("Navigation to " + event.url + " prevented");
         return false;
@@ -256,7 +313,6 @@ app.whenReady().then(() => {
 
     createMenu();
     createMainWindow();
-    createConfigWindow()
 });
 
 app.on('activate', () => {