Compare commits

...

5 Commits

Author SHA1 Message Date
Michael Ochmann b27d6d0170 fixed main menu on linux and windows 9 months ago
Michael Ochmann 87e2bf0b2f improved "doubleclick to maximize" 1 year ago
Michael Ochmann cc51075190 now locking settings if write is occuring 1 year ago
Michael Ochmann b8ad7b57da added functionality to restore former window size 1 year ago
Michael Ochmann ac6c5b0ce1 added "Iosevka" font to app package 1 year ago
  1. 4
      package-lock.json
  2. 2
      src/MainMenu.js
  3. 22
      src/SettingsManager.js
  4. 14
      src/WindowManager.js
  5. 31
      src/ui/src/assets/css/_fonts.scss
  6. 64
      src/ui/src/assets/css/_forms.scss
  7. 4
      src/ui/src/assets/css/_settings.scss
  8. 2
      src/ui/src/assets/css/_variables.scss
  9. 2
      src/ui/src/assets/css/ation.scss
  10. BIN
      src/ui/src/assets/fonts/iosevka/Iosevka-Bold.ttf
  11. BIN
      src/ui/src/assets/fonts/iosevka/Iosevka-BoldItalic.ttf
  12. BIN
      src/ui/src/assets/fonts/iosevka/Iosevka-Italic.ttf
  13. BIN
      src/ui/src/assets/fonts/iosevka/Iosevka-Light.ttf
  14. BIN
      src/ui/src/assets/fonts/iosevka/Iosevka-LightItalic.ttf
  15. BIN
      src/ui/src/assets/fonts/iosevka/Iosevka-Regular.ttf
  16. 25
      src/ui/src/components/Toolbar.js
  17. 29
      src/ui/src/components/settings/General.js
  18. 12
      src/ui/src/components/shared/Toggle.js

4
package-lock.json generated

@ -1,12 +1,12 @@
{ {
"name": "ation", "name": "ation",
"version": "0.3.3", "version": "0.4.0",
"lockfileVersion": 2, "lockfileVersion": 2,
"requires": true, "requires": true,
"packages": { "packages": {
"": { "": {
"name": "ation", "name": "ation",
"version": "0.3.3", "version": "0.4.0",
"license": "MIT", "license": "MIT",
"dependencies": { "dependencies": {
"font-list": "^1.4.5", "font-list": "^1.4.5",

@ -57,7 +57,7 @@ class MainMenu {
role : "windowMenu" role : "windowMenu"
} }
]; ];
template[1].submenu.push({ template[process.platform === "darwin" ? 1 : 0].submenu.push({
id : "recent-files", id : "recent-files",
label : "Recent files", label : "Recent files",
enabled : this.app.recentFiles.length > 0, enabled : this.app.recentFiles.length > 0,

@ -8,17 +8,23 @@ const path = require("path");
class SettingsManager { class SettingsManager {
app; app;
data; data;
locked;
constructor(app) { constructor(app) {
this.app = app; this.app = app;
this.data = null; this.data = null;
this.locked = false;
if (!SettingsManager.CheckFileSystem()) { if (!SettingsManager.CheckFileSystem()) {
if (!fsn.existsSync(SettingsManager.Folder)) if (!fsn.existsSync(SettingsManager.Folder))
fsn.mkdirSync(SettingsManager.Folder); fsn.mkdirSync(SettingsManager.Folder);
fsn.writeFileSync(SettingsManager.File, "{}"); fsn.writeFileSync(SettingsManager.File, "{}");
} }
this.data = JSON.parse(fsn.readFileSync(SettingsManager.File, {encoding : "utf-8"})); try {
this.data = JSON.parse(fsn.readFileSync(SettingsManager.File, {encoding : "utf-8"})) ?? {};
} catch (error) {
this.data = {};
}
ipcMain.handle("SettingsManager::get", (_, key, defaultValue = null) => this.get(key, defaultValue)); ipcMain.handle("SettingsManager::get", (_, key, defaultValue = null) => this.get(key, defaultValue));
ipcMain.handle("SettingsManager::set", (_, key, value) => this.set(key, value)); ipcMain.handle("SettingsManager::set", (_, key, value) => this.set(key, value));
@ -41,9 +47,15 @@ class SettingsManager {
this.app.windowManager.mainWindow?.send("SettingsManager::change", this.data); this.app.windowManager.mainWindow?.send("SettingsManager::change", this.data);
} }
save() { async save() {
fs.writeFile(SettingsManager.File, JSON.stringify(this.data, null, 4)); if (this.locked) {
setTimeout(async () => await this.save(), 200);
return;
}
this.locked = true;
await fs.writeFile(SettingsManager.File, JSON.stringify(this.data, null, 4));
this.change(); this.change();
this.locked = false;
} }
async reset() { async reset() {

@ -24,9 +24,15 @@ class WindowManager {
} }
init() { init() {
const shouldRestore = this.app.settingsManager.get("restoreWindow", false);
const width = shouldRestore ? this.app.settingsManager.get("windowWidth", 800) : 800;
const height = shouldRestore ? this.app.settingsManager.get("windowHeight", 600) : 600;
this.mainWindow = WindowManager._CreateWindow({ this.mainWindow = WindowManager._CreateWindow({
fullscreen : false, fullscreen : false,
fullscreenable : true fullscreenable : true,
width,
height
}); });
this.windows.settings = WindowManager._CreateWindow({ this.windows.settings = WindowManager._CreateWindow({
height : 300, height : 300,
@ -36,6 +42,12 @@ class WindowManager {
show : false show : false
}, this.mainWindow, false); }, this.mainWindow, false);
this.mainWindow.on("resize", () => {
const [width, height] = this.mainWindow.getSize();
this.app.settingsManager.set("windowWidth", width);
this.app.settingsManager.set("windowHeight", height);
});
// on windows and linux we need to hide the main menu in the settings // on windows and linux we need to hide the main menu in the settings
// window, because it would look odd. // window, because it would look odd.
if (["win32", "linux"].includes(process.platform)) { if (["win32", "linux"].includes(process.platform)) {

@ -0,0 +1,31 @@
@font-face {
font-family: "Iosevka";
src: url("#{$font-path}/iosevka/Iosevka-Regular.ttf");
}
@font-face {
font-family: "Iosevka";
src: url("#{$font-path}/iosevka/Iosevka-Italic.ttf");
font-style: italic;
}
@font-face {
font-family: "Iosevka";
src: url("#{$font-path}/iosevka/Iosevka-Bold.ttf");
font-weight: bold;
}
@font-face {
font-family: "Iosevka";
src: url("#{$font-path}/iosevka/Iosevka-BoldItalic.ttf");
font-weight: bold;
font-style: italic;
}
@font-face {
font-family: "Iosevka";
src: url("#{$font-path}/iosevka/Iosevka-Light.ttf");
font-weight: 100;
}
@font-face {
font-family: "Iosevka";
src: url("#{$font-path}/iosevka/Iosevka-LightItalic.ttf");
font-weight: 100;
font-style: italic;
}

@ -52,3 +52,67 @@ select {
} }
} }
} }
$size : 20px;
$spacing : 3px;
.toggle {
position: relative;
display: inline-block;
width: calc(($size + $spacing) * 2);
height: calc($size + 2 * $spacing);
vertical-align: middle;
margin: 0;
input {
opacity: 0;
width: 0;
height: 0;
&:checked {
& + .slider {
background-color: color(hightlight);
}
}
&:checked + .slider::before {
transform: translateX($size);
}
}
.slider {
position: absolute;
cursor: pointer;
top: 0;
left: 0;
right: 0;
bottom: 0;
background-color: color(fadedForeground);
-webkit-transition: .4s;
transition: .4s;
&::before {
position: absolute;
content: "";
height: $size;
width: $size;
left: $spacing;
bottom: $spacing;
background-color: color(sidebarBackground);
-webkit-transition: .4s;
transition: .4s;
}
&.round {
border-radius: calc($size * 2);
&::before {
border-radius: 50%;
}
}
}
& + label {
vertical-align: middle;
}
}

@ -73,6 +73,10 @@
align-self: flex-start; align-self: flex-start;
} }
} }
&.mb {
margin-bottom: 2rem;
}
} }
} }

@ -17,3 +17,5 @@ $colors : (
--color-#{$colorName} : #{$colorValue}; --color-#{$colorName} : #{$colorValue};
} }
} }
$font-path : "../fonts";

@ -5,6 +5,7 @@
@import "forms"; @import "forms";
@import "toolbar"; @import "toolbar";
@import "settings"; @import "settings";
@import "fonts";
@import "window"; @import "window";
@import "noFile"; @import "noFile";
@ -38,6 +39,7 @@ body {
app-region: drag; app-region: drag;
height: 30px; height: 30px;
width: 100%; width: 100%;
user-select: none;
} }
::selection { ::selection {

@ -1,4 +1,4 @@
import React, {useContext} from "react"; import React, {useContext, useEffect, useRef} from "react";
import {Folder2Open, Cast, InfoCircle, XSquare, LayoutSplit} from "react-bootstrap-icons"; import {Folder2Open, Cast, InfoCircle, XSquare, LayoutSplit} from "react-bootstrap-icons";
@ -8,6 +8,7 @@ import Mode from "../models/Mode";
import {ReactComponent as Logo} from "../assets/images/logo_ation.svg"; import {ReactComponent as Logo} from "../assets/images/logo_ation.svg";
const Toolbar = ({openFile, setShowTips, version, toggleEdit}) => { const Toolbar = ({openFile, setShowTips, version, toggleEdit}) => {
const toolbar = useRef();
const {setMode, setSlide, slideCount} = useContext(SlideContext); const {setMode, setSlide, slideCount} = useContext(SlideContext);
const present = () => { const present = () => {
@ -16,12 +17,30 @@ const Toolbar = ({openFile, setShowTips, version, toggleEdit}) => {
document.documentElement.requestFullscreen(); document.documentElement.requestFullscreen();
}; };
const toggleMaximize = () => { const toggleMaximize = event => {
if (event.target !== toolbar.current)
return;
window.api.maximize(); window.api.maximize();
event.stopPropagation();
}; };
// prevent text selection on doubleclick
useEffect(() => {
const tBar = toolbar.current;
const doubleClickListener = event => {
if (event.detail > 1)
event.preventDefault();
};
tBar?.addEventListener("mousedown", doubleClickListener);
return () => {
tBar?.removeEventListener("mousedown", doubleClickListener);
};
}, [toolbar]);
return ( return (
<nav className="toolbar" onDoubleClick={toggleMaximize}> <nav className="toolbar" onDoubleClick={toggleMaximize} ref={toolbar}>
<button onClick={openFile} title="Open file [⌘+O]"><Folder2Open /></button> <button onClick={openFile} title="Open file [⌘+O]"><Folder2Open /></button>
<button onClick={present} title="Start presentation [F5]"><Cast /></button> <button onClick={present} title="Start presentation [F5]"><Cast /></button>
<Logo /> <Logo />

@ -1,15 +1,36 @@
import React from "react"; import React, {useState, useEffect} from "react";
import Toggle from "../shared/Toggle";
const General = () => { const General = () => {
const [restoreWindow, setRestoreWindow] = useState(false);
useEffect(() => {
(async () => {
setRestoreWindow(await window.appSettings.get("restoreWindow", false));
})(setRestoreWindow);
}, []);
const changeRestoreWindow = event => {
const value = event.target.checked === true;
setRestoreWindow(value);
window.appSettings.set("restoreWindow", value);
};
const reset = () => { const reset = () => {
window.appSettings.reset(); window.appSettings.reset();
} }
return ( return (
<section style={{textAlign : "center"}}> <>
<button className="danger" onClick={reset}>reset all settings to default</button> <section className="grid mb">
</section> <label>Restore window size:</label>
<Toggle checked={restoreWindow} onChange={changeRestoreWindow} />
</section>
<section style={{textAlign : "center"}}>
<button className="danger" onClick={reset}>reset all settings to default</button>
</section>
</>
); );
}; };

@ -0,0 +1,12 @@
import React from "react";
const Toggle = ({...props}) => {
return (
<label className="toggle">
<input type="checkbox" {...props} />
<span className="slider round"></span>
</label>
);
};
export default Toggle;
Loading…
Cancel
Save