diff --git a/src/Ation.js b/src/Ation.js index 27330c2..d7946b4 100644 --- a/src/Ation.js +++ b/src/Ation.js @@ -15,7 +15,6 @@ class Ation { app.whenReady().then(async () => { protocol.registerFileProtocol("slideimg", (request, callback) => { const path = request.url.replace(/^slideimg:\/\//, ""); - console.log(path); callback(path); }); }); diff --git a/src/ui/src/assets/css/_forms.scss b/src/ui/src/assets/css/_forms.scss index 5f4dfec..ec1b5ad 100644 --- a/src/ui/src/assets/css/_forms.scss +++ b/src/ui/src/assets/css/_forms.scss @@ -1,5 +1,6 @@ button { border: none; + outline: 0 !important; background: color(scrollbar); color: color(foreground); padding: 0.5rem 2rem; @@ -20,6 +21,7 @@ button { svg { margin-right: 0.3rem; vertical-align: middle; + color: color(hightlight); } } diff --git a/src/ui/src/assets/css/_slide.scss b/src/ui/src/assets/css/_slide.scss index d416387..2b9fa62 100644 --- a/src/ui/src/assets/css/_slide.scss +++ b/src/ui/src/assets/css/_slide.scss @@ -5,7 +5,6 @@ flex-direction: column; align-items: center; justify-content: center; - user-select: none; padding: 8vw; text-align: center; aspect-ratio: 1.333; diff --git a/src/ui/src/assets/css/_slidesList.scss b/src/ui/src/assets/css/_slidesList.scss index 50ff874..4423577 100644 --- a/src/ui/src/assets/css/_slidesList.scss +++ b/src/ui/src/assets/css/_slidesList.scss @@ -14,6 +14,7 @@ .slide { width: 100vw; height: auto; + user-select: none; margin: 5% 0 0 5%; aspect-ratio: 1.333; -webkit-transform-origin: top left; diff --git a/src/ui/src/assets/css/_tips.scss b/src/ui/src/assets/css/_tips.scss new file mode 100644 index 0000000..ad4f01b --- /dev/null +++ b/src/ui/src/assets/css/_tips.scss @@ -0,0 +1,46 @@ +.tips { + display: flex; + align-items: center; + justify-content: center; + position: absolute; + top: 0; + left: 0; + width: 100vw; + user-select: none; + height: 100vh; + z-index: 2000; + background: rgba(0,0,0,0.5); + backdrop-filter: blur(6px); + + .inner { + background: color(mainBackground); + box-shadow: 0 0 2rem rgba(0,0,0,0.6); + text-transform: uppercase; + width: 80%; + height: 70%; + max-width: 800px; + max-height: 600px; + border-radius: 1rem; + padding: 0 4rem; + text-align: center; + opacity: 0.9; + + h1 { + font-family: "Iosevka", sans-serif; + font-weight: normal; + font-size: 2rem; + } + + article { + display: grid; + grid-template-columns: 3fr 1fr; + text-align: left; + line-height: 2rem; + + kbd { + font-size: 1rem; + text-align: right; + } + } + } +} \ No newline at end of file diff --git a/src/ui/src/assets/css/_window.scss b/src/ui/src/assets/css/_window.scss index bb81e31..a5f1db5 100644 --- a/src/ui/src/assets/css/_window.scss +++ b/src/ui/src/assets/css/_window.scss @@ -27,6 +27,7 @@ & > .slide:first-child { position: absolute; margin: 0; + user-select: none; top: 0; left: 0; width: 100vw; diff --git a/src/ui/src/assets/css/ation.scss b/src/ui/src/assets/css/ation.scss index d7ac640..41ab486 100644 --- a/src/ui/src/assets/css/ation.scss +++ b/src/ui/src/assets/css/ation.scss @@ -7,6 +7,7 @@ @import "window"; @import "noFile"; +@import "tips"; @import "slidesList"; @import "slide"; @import "blackout"; diff --git a/src/ui/src/components/Ation.js b/src/ui/src/components/Ation.js index b0f5539..bb3562f 100644 --- a/src/ui/src/components/Ation.js +++ b/src/ui/src/components/Ation.js @@ -7,6 +7,7 @@ import KeyboardControl from "./KeyboardControl"; import Blackout from "./Blackout"; import NoFile from "./NoFile"; import Toolbar from "./Toolbar"; +import Tips from "./Tips"; import SlideContext from "../shared/SlideContext"; @@ -15,6 +16,7 @@ const Ation = () => { const [deck, setDeck] = useState([]); const [slide, setSlide] = useState(0); const [basePath, setBasePath] = useState(""); + const [showTips, setShowTips] = useState(false); const openFile = async () => { const [basePath, slideDeck] = await window.api.openFile(); @@ -31,14 +33,15 @@ const Ation = () => { return (
- +
+
- +
); }; diff --git a/src/ui/src/components/KeyboardControl.js b/src/ui/src/components/KeyboardControl.js index ab3efe1..d878cdf 100644 --- a/src/ui/src/components/KeyboardControl.js +++ b/src/ui/src/components/KeyboardControl.js @@ -1,12 +1,22 @@ -import {useContext, useEffect} from "react"; +import {useContext, useEffect, version} from "react"; import SlideContext from "../shared/SlideContext"; import Mode from "../models/Mode"; -const KeyboardControl = ({openFile, mode, setMode, deck}) => { +const KeyboardControl = ({openFile, mode, setMode, deck, setShowTips}) => { const {slide, setSlide} = useContext(SlideContext); useEffect(() => { + const keyUpHandler = event => { + switch(event.key) { + case "Tab": + setShowTips(false); + break; + default: + return; + } + } + const keyHandler = event => { switch(event.key) { case "o": @@ -15,9 +25,9 @@ const KeyboardControl = ({openFile, mode, setMode, deck}) => { openFile(); break; default: - console.log(event.key); + break; } - if (!mode || !setMode || !deck) + if (!mode || !setMode || !deck || !setShowTips) return; switch (event.key) { @@ -45,6 +55,10 @@ const KeyboardControl = ({openFile, mode, setMode, deck}) => { return; setMode(mode === Mode.BLACKOUT ? Mode.PRESENT : Mode.BLACKOUT); break; + case "Tab": + event.preventDefault(); + setShowTips(true); + break; default: return; } @@ -56,14 +70,16 @@ const KeyboardControl = ({openFile, mode, setMode, deck}) => { }; window.addEventListener("keydown", keyHandler); + window.addEventListener("keyup", keyUpHandler); window.addEventListener("fullscreenchange", fullscreenHandler); return () => { window.removeEventListener("keydown", keyHandler); + window.removeEventListener("keyup", keyUpHandler); window.removeEventListener("fullscreenchange", fullscreenHandler); } - }, [slide, setSlide, mode, setMode, deck]); + }, [slide, setSlide, mode, setMode, deck, setShowTips, openFile]); }; export default KeyboardControl; \ No newline at end of file diff --git a/src/ui/src/components/Tips.js b/src/ui/src/components/Tips.js new file mode 100644 index 0000000..2f453ae --- /dev/null +++ b/src/ui/src/components/Tips.js @@ -0,0 +1,33 @@ +import React, {Fragment} from "react"; + +const Cheatsheet = Object.freeze([ + ["Start presentation", "F5"], + ["Stop presentation", "ESC"], + ["Open file", "Ctrl+O"], + ["Next slide", "→, Page up"], + ["Last slide", "←, Page down"], + ["Black screen out", "B"], + ["Show/Hide tips", "TAB"] +]); + +const Tips = ({show}) => { + return ( + show ? +
+
+

Cheatsheet

+
+ {Cheatsheet.map(([description, key]) => ( + + + {key} + + ))} +
+
+
+ : null + ); +}; + +export default Tips; \ No newline at end of file diff --git a/src/ui/src/components/Toolbar.js b/src/ui/src/components/Toolbar.js index 3cfcc58..0cfc5c5 100644 --- a/src/ui/src/components/Toolbar.js +++ b/src/ui/src/components/Toolbar.js @@ -1,11 +1,11 @@ import React, {useContext} from "react"; -import {Folder2Open, Cast} from "react-bootstrap-icons"; +import {Folder2Open, Cast, InfoCircle} from "react-bootstrap-icons"; import SlideContext from "../shared/SlideContext"; import Mode from "../models/Mode"; -const Toolbar = ({openFile}) => { +const Toolbar = ({openFile, setShowTips}) => { const {setMode, setSlide} = useContext(SlideContext); const present = () => { @@ -16,8 +16,9 @@ const Toolbar = ({openFile}) => { return ( ); };