From d403fb62e2d0d54d217f6c9ae5d76ca5051855ad Mon Sep 17 00:00:00 2001 From: Andrew Lorimer Date: Tue, 27 Apr 2021 21:41:03 +1000 Subject: [PATCH] add keyboard shortcuts, icons, preloading --- icons/first.svg | 1 + icons/last.svg | 1 + icons/left.svg | 1 + icons/right.svg | 1 + index.html | 35 ++++++----- ppt-control.js | 94 +++++++++++++++++++++++++---- obs_ppt_server.py => ppt_control.py | 9 +-- settings.js | 11 ++-- style.css | 30 +++++++-- 9 files changed, 142 insertions(+), 41 deletions(-) create mode 100644 icons/first.svg create mode 100644 icons/last.svg create mode 100644 icons/left.svg create mode 100644 icons/right.svg rename obs_ppt_server.py => ppt_control.py (94%) diff --git a/icons/first.svg b/icons/first.svg new file mode 100644 index 0000000..8d0f155 --- /dev/null +++ b/icons/first.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/icons/last.svg b/icons/last.svg new file mode 100644 index 0000000..7064515 --- /dev/null +++ b/icons/last.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/icons/left.svg b/icons/left.svg new file mode 100644 index 0000000..acb94c1 --- /dev/null +++ b/icons/left.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/icons/right.svg b/icons/right.svg new file mode 100644 index 0000000..a9e5aa7 --- /dev/null +++ b/icons/right.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/index.html b/index.html index a1a4c3f..5a0cec6 100755 --- a/index.html +++ b/index.html @@ -6,32 +6,39 @@ ppt-control +
+

Current slide

+

Next slide

+
-

- - - - - - - Current: /? -

- - Show current slide - Show next slide - -

Not connected

+
+

+ + + + + Current: /? + + +

+ + Show current slide + Show next slide + Keyboard shortcuts + +

Not connected

+
diff --git a/ppt-control.js b/ppt-control.js index 7496f1b..7e4c312 100644 --- a/ppt-control.js +++ b/ppt-control.js @@ -1,3 +1,5 @@ +var preloaded = false; + function imageRefresh(id) { img = document.getElementById(id); var d = new Date; @@ -17,9 +19,6 @@ function startWebsocket() { var websocket = startWebsocket(); -//if (window.obssstudio) { -//} - var prev = document.querySelector('#prev'), next = document.querySelector('#next'), first = document.querySelector('#first'), @@ -30,12 +29,15 @@ var prev = document.querySelector('#prev'), current = document.querySelector('#current'), total = document.querySelector('#total'), users = document.querySelector('.users'), - prev_img = document.querySelector('#prev_img'), + current_img = document.querySelector('#current_img'), next_img = document.querySelector('#next_img'), current_div = document.querySelector('#current_div'), next_div = document.querySelector('#next_div'), + controls_container = document.querySelector('#controls_container'), + controls_container_inner = document.querySelector('#controls_container_inner'), show_current = document.querySelector('#show_current'), - show_next = document.querySelector('#show_next'); + show_next = document.querySelector('#show_next'), + shortcuts = document.querySelector('#shortcuts'); prev.onclick = function (event) { websocket.send(JSON.stringify({action: 'prev'})); @@ -69,34 +71,89 @@ current.addEventListener('keyup',function(e){ if (e.which == 13) this.blur(); }); +current_img.onclick = function (event) { + next.click() +} + +next_img.onclick = function (event) { + next.click() +} + + function sync_current() { - console.log("State of current checkbox changed"); if (show_current.checked) { current_div.style.display = "block"; slide_label.style.display = "none"; next_div.style.width = "25%"; } else { current_div.style.display = "none"; - slide_label.style.display = "block"; - next_div.style.width = "95%"; + slide_label.style.display = "inline"; + next_div.style.width = "calc(100% - 20px)"; } + set_control_width(); saveSettings(); } show_current.onclick = sync_current; function sync_next() { - console.log("State of next checkbox changed"); if (show_next.checked) { next_div.style.display = "block"; current_div.style.width = "70%"; } else { next_div.style.display = "none"; - current_div.style.width = "95%"; + current_div.style.width = "calc(100% - 20px)"; } + set_control_width(); saveSettings(); } show_next.onclick = sync_next; +function set_control_width() { + var width = window.innerWidth + || document.documentElement.clientWidth + || document.body.clientWidth; + if (show_current.checked && show_next.checked && width > 800) { + controls_container_inner.style.width = "70%" + } else { + controls_container_inner.style.width = "100%" + } +} + + +document.addEventListener('keydown', function (e) { + if (shortcuts.checked) { + switch (e.key) { + case "Left": + case "ArrowLeft": + case "Up": + case "ArrowUp": + case "k": + case "K": + prev.click(); + break; + case " ": + case "Spacebar": + case "Enter": + case "Right": + case "ArrowRight": + case "Down": + case "ArrowDown": + case "j": + case "J": + next.click(); + break; + case "b": + case "B": + black.click(); + case "w": + case "W": + white.click(); + default: + return + } + } +}); + websocket.onmessage = function (event) { data = JSON.parse(event.data); switch (data.type) { @@ -110,7 +167,8 @@ websocket.onmessage = function (event) { current_img.src = "/white.jpg"; break; default: - current_img.src = "/cache/" + data.current + ".jpg?t=" + d.getTime(); + //current_img.src = "/cache/" + data.current + ".jpg?t=" + d.getTime(); + current_img.src = "/cache/" + data.current + ".jpg"; break; } if (data.current == data.total + 1) { @@ -125,6 +183,7 @@ websocket.onmessage = function (event) { current.value = data.current; } total.textContent = data.total; + document.title = data.name; break; case 'users': users.textContent = ( @@ -135,6 +194,18 @@ websocket.onmessage = function (event) { console.error( "unsupported event", data); } + if (!preloaded) { + var i = 0 + var preload = []; + for (let i=1; i<=Number(total.textContent); i++) { + image = new Image(); + image.src = "/cache/" + i + ".jpg"; + preload.push(image); + console.log("Preloaded image " + i); + } + preloaded = true; + } + }; var interval = setInterval(refresh, 5000); @@ -142,3 +213,4 @@ var interval = setInterval(refresh, 5000); function refresh() { websocket.send(JSON.stringify({action: 'refresh'})); } + diff --git a/obs_ppt_server.py b/ppt_control.py similarity index 94% rename from obs_ppt_server.py rename to ppt_control.py index 4172d94..75cf1b0 100755 --- a/obs_ppt_server.py +++ b/ppt_control.py @@ -60,7 +60,6 @@ class Handler(server.SimpleHTTPRequestHandler): path = os.path.join(path, word) if trailing_slash: path += '/' - print(path) return path @@ -68,7 +67,7 @@ def run_http(): http_server = server.HTTPServer(("", 80), Handler) http_server.serve_forever() -STATE = {"connected": 0, "current": 0, "total": 0, "visible": 0} +STATE = {"connected": 0, "current": 0, "total": 0, "visible": 0, "name": ""} USERS = set() @@ -86,6 +85,7 @@ async def notify_state(): STATE["current"] = current_slideshow.current_slide() STATE["total"] = current_slideshow.total_slides() STATE["visible"] = current_slideshow.visible() + STATE["name"] = current_slideshow.name() if USERS: # asyncio.wait doesn't accept an empty list message = state_event() await asyncio.wait([user.send(message) for user in USERS]) @@ -163,9 +163,7 @@ def run_ws(): pythoncom.CoInitializeEx(pythoncom.COINIT_MULTITHREADED) asyncio.set_event_loop(asyncio.new_event_loop()) start_server = websockets.serve(ws_handle, "0.0.0.0", 5678) - print("Initialised websocket server") asyncio.get_event_loop().run_until_complete(start_server) - print("Running websocket server until complete") asyncio.get_event_loop().run_forever() def start_server(): @@ -302,7 +300,6 @@ def get_ppt_instance(): return instance def get_current_slideshow(): - print(str(current_slideshow)) return current_slideshow @@ -318,7 +315,7 @@ if __name__ == "__main__": STATE["connected"] = 1 STATE["current"] = current_slideshow.current_slide() STATE["total"] = current_slideshow.total_slides() - print("Connected to PowerPoint instance " + str(get_current_slideshow())) + print("Connected to PowerPoint instance") break except ValueError as e: current_slideshow = None diff --git a/settings.js b/settings.js index 2807801..eb94f8e 100644 --- a/settings.js +++ b/settings.js @@ -25,21 +25,22 @@ function getCookie(cname) { } function saveSettings() { - settingsString = JSON.stringify({showcurrent: show_current.checked, shownext: show_next.checked}); - console.log("Saving cookie " + settingsString); + settingsString = JSON.stringify({showcurrent: show_current.checked, shownext: show_next.checked, enable_shortcuts: shortcuts.checked}); setCookie(COOKIENAME, settingsString, COOKIEEXP); } function initSettings() { - console.log("Retrieving cookie"); if (getCookie(COOKIENAME) == 0) { - console.log("No cookie found - setting new cookie"); + if (window.obssstudio) { + shortcuts.checked = False; + show_current.checked = False; + } saveSettings() } else { cookie = JSON.parse(getCookie(COOKIENAME)); - console.log("Found cookie " + cookie); show_current.checked = cookie.showcurrent; show_next.checked = cookie.shownext; + shortcuts.checked = cookie.enable_shortcuts; sync_current(); sync_next(); } diff --git a/style.css b/style.css index 5b2be56..01c5734 100644 --- a/style.css +++ b/style.css @@ -30,10 +30,6 @@ p { clear: both; } -::-webkit-scrollbar { - //display: none; -} - body { background: #3a393a; color: #efefef; @@ -52,6 +48,30 @@ input { @media only screen and (max-width: 800px) { #current_div, #next_div { - width: 95% !important; + width: calc(100% - 20px) !important; } } + +.icon { + width: 50px; + filter: invert(88%) sepia(4%) saturate(15%) hue-rotate(18deg) brightness(92%) contrast(97%); +} + +.icon:hover { + cursor: pointer; + filter: invert(100%) sepia(24%) saturate(1720%) hue-rotate(187deg) brightness(123%) contrast(87%); +} + +.icon#first, .icon#last { + width: 20px; + margin-bottom: 10px; +} + +button { + float: right; + margin: 0 10px 0 0; +} + +input[type='checkbox'] { + font-size: 15px; +} -- 2.47.1