From 11d5983028e20885f983a744a5c174bdc56b1917 Mon Sep 17 00:00:00 2001 From: Michael Ochmann Date: Thu, 6 Oct 2022 00:05:55 +0200 Subject: [PATCH] more groundwork torwards a settings dialog --- contextAPI.js | 9 +++- package-lock.json | 5 ++ package.json | 1 + src/Ation.js | 31 ++++++----- src/FontManager.js | 13 +++++ src/SettingsManager.js | 51 ++++++++++++++++++ src/WindowManager.js | 1 + src/ui/package-lock.json | 5 ++ src/ui/src/assets/css/_forms.scss | 8 +++ src/ui/src/assets/css/_noFile.scss | 9 ---- src/ui/src/assets/css/_settings.scss | 63 ++++++++++++++++++++-- src/ui/src/assets/css/_variables.scss | 4 +- src/ui/src/assets/css/ation.scss | 10 ++++ src/ui/src/components/Ation.js | 5 +- src/ui/src/components/settings/General.js | 28 ++++++++++ src/ui/src/components/settings/Navbar.js | 19 ++++--- src/ui/src/components/settings/Settings.js | 30 +++++++++-- src/ui/src/index.js | 2 +- 18 files changed, 255 insertions(+), 39 deletions(-) create mode 100644 src/FontManager.js create mode 100644 src/SettingsManager.js create mode 100644 src/ui/src/components/settings/General.js diff --git a/contextAPI.js b/contextAPI.js index aa05524..835963d 100644 --- a/contextAPI.js +++ b/contextAPI.js @@ -23,5 +23,12 @@ contextBridge.exposeInMainWorld("api", { closeFile : () => ipcRenderer.send("Ation::closeFile"), clearCache : () => webFrame.clearCache(), - appVersion : async () => await ipcRenderer.invoke("Ation::appVersion") + appVersion : async () => await ipcRenderer.invoke("Ation::appVersion"), + fonts : async () => await ipcRenderer.invoke("FontManager::fonts"), + resize : size => ipcRenderer.invoke("SettingsManager::resize", size) +}); + +contextBridge.exposeInMainWorld("appSettings", { + get : async (key, defaultValue = null) => await ipcRenderer.invoke("SettingsManager::get", key, defaultValue), + set : async (key, value) => await ipcRenderer.invoke("SettingsManager::set", key, value) }); \ No newline at end of file diff --git a/package-lock.json b/package-lock.json index ea128c2..180f731 100644 --- a/package-lock.json +++ b/package-lock.json @@ -1534,6 +1534,11 @@ "integrity": "sha512-VQLG33o04KaQ8uYi2tVNbdrWp1QWxNNea+nmIB4EVM28v0hmP17z7aG1+wAkNzVq4KeXTq3221ye5qTJP91JwA==", "dev": true }, + "font-list": { + "version": "1.4.5", + "resolved": "https://registry.npmjs.org/font-list/-/font-list-1.4.5.tgz", + "integrity": "sha512-mLi7Sb4iitgk3mJsTZZDbixssHLoJB4/onWGlQOvTSPW8YPBDQNaMTGOdZ92axQI4UNWwPxV5FmCBOEo1Us7lg==" + }, "form-data": { "version": "4.0.0", "resolved": "https://registry.npmjs.org/form-data/-/form-data-4.0.0.tgz", diff --git a/package.json b/package.json index 34f337a..0fe6f60 100644 --- a/package.json +++ b/package.json @@ -15,6 +15,7 @@ "author": "Michael Ochmann ", "license": "MIT", "dependencies": { + "font-list": "^1.4.5", "marked": "^4.1.0" }, "build": { diff --git a/src/Ation.js b/src/Ation.js index 246c44e..6cdf3f7 100644 --- a/src/Ation.js +++ b/src/Ation.js @@ -1,18 +1,22 @@ "use strict"; -const {app, protocol, dialog, ipcMain, Menu} = require("electron"); -const path = require("path"); -const fs = require("fs/promises"); -const fsn = require("fs"); +const {app, protocol, dialog, ipcMain, Menu, session} = require("electron"); +const path = require("path"); +const fs = require("fs/promises"); +const fsn = require("fs"); -const AppInfo = require("../package.json"); -const WindowManager = require("./WindowManager"); -const MainMenu = require("./MainMenu"); -const {parser} = require("./Parser"); +const AppInfo = require("../package.json"); +const WindowManager = require("./WindowManager"); +const FontManager = require("./FontManager"); +const SettingsManager = require("./SettingsManager"); +const MainMenu = require("./MainMenu"); +const {parser} = require("./Parser"); app.commandLine.appendSwitch("disable-http-cache"); class Ation { windowManager; + fontManager; + settingsManager; mainMenu; watcher; currentFile; @@ -20,10 +24,12 @@ class Ation { constructor() { if (Ation.Instances > 0) throw new Error("Only one Instance of Ation possible"); - this.currentFile = ""; - this.watcher = null; - this.windowManager = new WindowManager(this); - this.mainMenu = new MainMenu(this); + this.currentFile = ""; + this.watcher = null; + this.windowManager = new WindowManager(this); + this.fontManager = new FontManager(); + this.settingsManager = new SettingsManager(this); + this.mainMenu = new MainMenu(this); app.on("open-file", (_, path) => { this.fileToOpen = path; @@ -42,6 +48,7 @@ class Ation { if (["png", "jpg", "jpeg", "svg", "bmp", "gif", "tiff"].includes(extension.toLowerCase())) callback(uri); }); + }); } diff --git a/src/FontManager.js b/src/FontManager.js new file mode 100644 index 0000000..1af5fc9 --- /dev/null +++ b/src/FontManager.js @@ -0,0 +1,13 @@ +"use strict"; + +const {ipcMain} = require("electron"); +const FontList = require("font-list"); + +class FontManager { + + constructor() { + ipcMain.handle("FontManager::fonts", async () => await FontList.getFonts().catch(error => console.log(error))); + } +} + +module.exports = FontManager; \ No newline at end of file diff --git a/src/SettingsManager.js b/src/SettingsManager.js new file mode 100644 index 0000000..1edd18c --- /dev/null +++ b/src/SettingsManager.js @@ -0,0 +1,51 @@ +"use strict"; + +const {ipcMain, app} = require("electron"); +const fsn = require("fs"); +const fs = require("fs/promises") +const path = require("path"); + +class SettingsManager { + app; + data; + + constructor(app) { + this.app = app; + this.data = null; + + if (!SettingsManager.CheckFileSystem()) { + if (!fsn.existsSync(SettingsManager.Folder)) + fsn.mkdirSync(SettingsManager.Folder); + fsn.writeFileSync(SettingsManager.File, "{}"); + } + this.data = JSON.parse(fsn.readFileSync(SettingsManager.File, {encoding : "utf-8"})); + + ipcMain.handle("SettingsManager::resize", (_, height) => app.windowManager.windows.settings.setSize(800, height, true)); + ipcMain.handle("SettingsManager::get", (_, key, defaultValue = null) => this.get(key, defaultValue)); + ipcMain.handle("SettingsManager::set", (_, key, value) => this.set(key, value)); + } + + get(key, defaultValue = null) { + if (Object.keys(this.data).includes(key)) + return this.data[key]; + return defaultValue; + } + + set(key, value) { + this.data[key] = value; + this.save(); + } + + save() { + fs.writeFile(SettingsManager.File, JSON.stringify(this.data, null, 4)); + } + + static CheckFileSystem() { + + return fsn.existsSync(SettingsManager.Folder) && fsn.existsSync(SettingsManager.File); + } +} +SettingsManager.Folder = app.getPath("userData"); +SettingsManager.File = path.join(SettingsManager.Folder, "config.json"); + +module.exports = SettingsManager; \ No newline at end of file diff --git a/src/WindowManager.js b/src/WindowManager.js index ad79bfc..b28f6d9 100644 --- a/src/WindowManager.js +++ b/src/WindowManager.js @@ -37,6 +37,7 @@ class WindowManager { if (isDevelopment()) { globalShortcut.register("CommandOrControl+I", () => { this.mainWindow.toggleDevTools(); + this.windows.settings.toggleDevTools(); }); globalShortcut.register("CommandOrControl+R", () => { this.mainWindow.reload(); diff --git a/src/ui/package-lock.json b/src/ui/package-lock.json index a48dd76..286e332 100644 --- a/src/ui/package-lock.json +++ b/src/ui/package-lock.json @@ -5727,6 +5727,11 @@ "resolved": "https://registry.npmjs.org/follow-redirects/-/follow-redirects-1.15.2.tgz", "integrity": "sha512-VQLG33o04KaQ8uYi2tVNbdrWp1QWxNNea+nmIB4EVM28v0hmP17z7aG1+wAkNzVq4KeXTq3221ye5qTJP91JwA==" }, + "font-list": { + "version": "1.4.5", + "resolved": "https://registry.npmjs.org/font-list/-/font-list-1.4.5.tgz", + "integrity": "sha512-mLi7Sb4iitgk3mJsTZZDbixssHLoJB4/onWGlQOvTSPW8YPBDQNaMTGOdZ92axQI4UNWwPxV5FmCBOEo1Us7lg==" + }, "fork-ts-checker-webpack-plugin": { "version": "6.5.2", "resolved": "https://registry.npmjs.org/fork-ts-checker-webpack-plugin/-/fork-ts-checker-webpack-plugin-6.5.2.tgz", diff --git a/src/ui/src/assets/css/_forms.scss b/src/ui/src/assets/css/_forms.scss index ec1b5ad..f79c758 100644 --- a/src/ui/src/assets/css/_forms.scss +++ b/src/ui/src/assets/css/_forms.scss @@ -25,6 +25,14 @@ button { } } +select { + background: color(sidebarBackground); + color: color(foreground); + border: none; + border-radius: 6px; + padding: 0.2rem 0.5rem; +} + .checkbox { display: inline-block; width: 2vw; diff --git a/src/ui/src/assets/css/_noFile.scss b/src/ui/src/assets/css/_noFile.scss index 58c621d..5f9075d 100644 --- a/src/ui/src/assets/css/_noFile.scss +++ b/src/ui/src/assets/css/_noFile.scss @@ -25,13 +25,4 @@ } } } - - .titlebar { - position: absolute; - top: 0; - left: 0; - app-region: drag; - height: 30px; - width: 100%; - } } \ No newline at end of file diff --git a/src/ui/src/assets/css/_settings.scss b/src/ui/src/assets/css/_settings.scss index 30abb12..e9c12c9 100644 --- a/src/ui/src/assets/css/_settings.scss +++ b/src/ui/src/assets/css/_settings.scss @@ -1,22 +1,77 @@ .settings { - font-family: system-ui, -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, Oxygen, Ubuntu, Cantarell, 'Open Sans', 'Helvetica Neue', sans-serif; + overflow: hidden; + font-family: system-ui, -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, Oxygen, Ubuntu, Cantarell, "Open Sans", "Helvetica Neue", sans-serif; + + &, * { + user-select: none; + -webkit-user-drag: none; + } .navbar { padding: 1.5rem 0.5rem 0 0.5rem; background: color(sidebarBackground); - app-region: drag; - button { + a { + text-decoration: none; padding: 0.3rem 0.5rem; + display: inline-block; + text-align: center; + border: none; + outline: 0 !important; + color: color(fadedForeground); + margin: 0.5rem 0.1rem; + transition: all 0.2s ease-in-out; + border-radius: 5px; + cursor: pointer; + + &:first-child { + margin-left: 0; + } + + &.active { + color: color(hightlight); + } + &.active, &:hover { + background: color(active); + } svg { font-size: 1.3rem; + vertical-align: middle; } label { margin-top: 0.2rem; display: block; - font-size: 0.8rem; + font-size: 0.7rem; + } + } + } + + main { + padding: 1rem 2rem; + font-size: 0.8rem; + + .grid { + display: grid; + grid-template-columns: 1fr 2fr; + gap: 0.8rem; + row-gap: 0.5rem; + align-items: center; + + input, select { + max-width: 50%; + outline: 0 !important; + } + + > * { + &:nth-child(odd) { + justify-self: flex-end; + } + + &:nth-child(even) { + align-self: flex-start; + } } } } diff --git a/src/ui/src/assets/css/_variables.scss b/src/ui/src/assets/css/_variables.scss index 4688a8c..4bbc8b0 100644 --- a/src/ui/src/assets/css/_variables.scss +++ b/src/ui/src/assets/css/_variables.scss @@ -2,10 +2,12 @@ $colors : ( //background : #272822, background : #1a1a1a, foreground : #ddd, + fadedForeground : #888, sidebarBackground : #333, mainBackground : #222, scrollbar : rgba(255,255,255,0.2), - hightlight : rgb(230,193,123) + hightlight : rgb(230,193,123), + active : rgba(255,255,255,0.1) ); :root { diff --git a/src/ui/src/assets/css/ation.scss b/src/ui/src/assets/css/ation.scss index 69f1b7c..e68171f 100644 --- a/src/ui/src/assets/css/ation.scss +++ b/src/ui/src/assets/css/ation.scss @@ -27,4 +27,14 @@ body { background: color(background); color: color(foreground); font-family: system-ui, -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, Oxygen, Ubuntu, Cantarell, 'Open Sans', 'Helvetica Neue', sans-serif; + overflow: hidden; +} + +.titlebar { + position: absolute; + top: 0; + left: 0; + app-region: drag; + height: 30px; + width: 100%; } \ No newline at end of file diff --git a/src/ui/src/components/Ation.js b/src/ui/src/components/Ation.js index b5bb7d7..3b60e5b 100644 --- a/src/ui/src/components/Ation.js +++ b/src/ui/src/components/Ation.js @@ -12,6 +12,7 @@ import Tips from "./Tips"; import SlideContext from "../shared/SlideContext"; const Ation = () => { + const [font, setFont] = useState(""); const [mode, setMode] = useState(Mode.NORMAL); const [deck, setDeck] = useState([]); const [slide, setSlide] = useState(0); @@ -36,6 +37,8 @@ const Ation = () => { setDeck([]); }); (async set => set(await window.api.appVersion()))(setVersion); + (async setFont => setFont(await window.appSettings.get("font", "Iosevka")))(setFont); + }, [basePath, slide]); const openFile = () => { @@ -52,7 +55,7 @@ const Ation = () => {
- +
diff --git a/src/ui/src/components/settings/General.js b/src/ui/src/components/settings/General.js new file mode 100644 index 0000000..a4d2101 --- /dev/null +++ b/src/ui/src/components/settings/General.js @@ -0,0 +1,28 @@ +import React, {useState, useEffect} from "react"; + +const General = ({fonts}) => { + const [font, setFont] = useState(""); + + const changeFont = event => { + const value = event.target.value; + setFont(value); + window.appSettings.set("font", value); + }; + + useEffect(() => { + (async setFont => setFont(await window.appSettings.get("font", "Iosevka")))(setFont); + }, []); + + return ( +
+ + + + +
+ ); +}; + +export default General; \ No newline at end of file diff --git a/src/ui/src/components/settings/Navbar.js b/src/ui/src/components/settings/Navbar.js index 4c8a82e..c0e3519 100644 --- a/src/ui/src/components/settings/Navbar.js +++ b/src/ui/src/components/settings/Navbar.js @@ -1,16 +1,21 @@ -import React from "react"; +import React, {forwardRef} from "react"; -import {Gear} from "react-bootstrap-icons"; +import {NavLink} from "react-router-dom"; +import {Gear} from "react-bootstrap-icons"; -const Navbar = () => { +const Navbar = forwardRef((props, ref) => { return ( - ); -}; +}); export default Navbar; \ No newline at end of file diff --git a/src/ui/src/components/settings/Settings.js b/src/ui/src/components/settings/Settings.js index 1177f13..7269d5d 100644 --- a/src/ui/src/components/settings/Settings.js +++ b/src/ui/src/components/settings/Settings.js @@ -1,11 +1,35 @@ -import React from "react"; +import React, {useRef, useState, useEffect} from "react"; +import {Routes, Route, useLocation} from "react-router-dom"; -import Navbar from "./Navbar"; +import Navbar from "./Navbar"; +import General from "./General"; const Settings = () => { + const navbar = useRef(); + const content = useRef() + const location = useLocation(); + const [fonts, setFonts] = useState([]); + + useEffect(() => { + (async setFonts => setFonts(await window.api.fonts()))(setFonts); + }, []); + + useEffect(() => { + if (!navbar.current || !content.current) + return; + const newHeight = navbar.current.clientHeight + content.current.clientHeight; + window.api.resize(newHeight + 10); + }, [location, navbar, content]); + return (
- + +
+ + } /> + +
+
); }; diff --git a/src/ui/src/index.js b/src/ui/src/index.js index b8709f0..e6c207e 100644 --- a/src/ui/src/index.js +++ b/src/ui/src/index.js @@ -17,7 +17,7 @@ root.render( } /> - } /> + } />