diff options
-rw-r--r-- | index.html | 38 | ||||
-rw-r--r-- | move.svg | 2 | ||||
-rw-r--r-- | pugl.js | 109 | ||||
-rw-r--r-- | style.css | 26 |
4 files changed, 139 insertions, 36 deletions
@@ -20,12 +20,23 @@ <div id="page"> <div id="main"> <div id="ui"> - <div id="title"> - <img src="icon.png" alt="" id="title-icon"> pugl + <div id="top-area"> + <img src="icon.png" alt="" id="title-icon"> <span id="title">pugl</span> <input placeholder="Title" id="creation-title"> - <button id="about-button" class="img-button" title="about pugl"> - <img alt="about" src="data:image/svg+xml;base64,PHN2ZyB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciIHdpZHRoPSIzMiIgaGVpZ2h0PSIzMiI+CjxlbGxpcHNlIGN4PSIxNiIgY3k9IjE2IiByeD0iMTIiIHJ5PSIxMiIgc3Ryb2tlPSIjZmZmIiBzdHJva2Utd2lkdGg9IjMiIGZpbGw9Im5vbmUiIC8+Cjx0ZXh0IGZpbGw9IiNmZmYiIHg9IjE2IiB5PSIyNCIgZm9udC13ZWlnaHQ9ImJvbGQiIGZvbnQtZmFtaWx5PSJzYW5zLXNlcmlmIiBmb250LXNpemU9IjIwcHgiIHRleHQtYW5jaG9yPSJtaWRkbGUiPj88L3RleHQ+Cjwvc3ZnPgo="> - </button> + <div id="creation-buttons"> + <button id="list-creations" class="img-button" title="list creations"> + <img alt="list creations" src="data:image/svg+xml;base64,PHN2ZyB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciIHdpZHRoPSIzMiIgaGVpZ2h0PSIzMiI+PHBhdGggZD0iTTYgNyBMMjYgNyBNNiAxNiBMMjYgMTYgTTYgMjUgTDI2IDI1IiBzdHJva2U9IiNmZmYiIHN0cm9rZS13aWR0aD0iNCIgc3Ryb2tlLWxpbmVjYXA9InJvdW5kIi8+PC9zdmc+"> + </button> + <button id="about-button" class="img-button" title="about pugl"> + <img alt="about" src="data:image/svg+xml;base64,PHN2ZyB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciIHdpZHRoPSIzMiIgaGVpZ2h0PSIzMiI+PGVsbGlwc2UgY3g9IjE2IiBjeT0iMTYiIHJ4PSIxMiIgcnk9IjEyIiBzdHJva2U9IiNmOGYiIHN0cm9rZS13aWR0aD0iMyIgZmlsbD0ibm9uZSIgLz48dGV4dCBmaWxsPSIjZjhmIiB4PSIxNiIgeT0iMjQiIGZvbnQtd2VpZ2h0PSJib2xkIiBmb250LWZhbWlseT0ic2Fucy1zZXJpZiIgZm9udC1zaXplPSIyMHB4IiB0ZXh0LWFuY2hvcj0ibWlkZGxlIj4/PC90ZXh0Pjwvc3ZnPg=="> + </button> + <button id="new-creation" class="img-button" title="new creation"> + <img alt="new creation" src="data:image/svg+xml;base64,PHN2ZyB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciIHdpZHRoPSIzMiIgaGVpZ2h0PSIzMiI+PHBhdGggZD0iTTE2IDYgTDE2IDI2IE02IDE2IEwyNiAxNiIgc3Ryb2tlPSIjOGY4IiBzdHJva2Utd2lkdGg9IjQiIHN0cm9rZS1saW5lY2FwPSJyb3VuZCIvPjwvc3ZnPg=="> + </button> + <button id="delete-creation" class="img-button" title="delete creation"> + <img alt="delete creation" src="x.svg"> + </button> + </div> </div> <form action="#" method="dialog" id="code-form" class="ui-section inline-block"> <input type="text" placeholder="Code" id="code"> @@ -101,6 +112,23 @@ <button>close</button> </form> </dialog> + <dialog id="creations-dialog"> + <h3>saved creations</h3> + <hr> + <div id="creations"></div> + <br> + <form method="dialog"> + <button>close</button> + </form> + </dialog> + <dialog id="delete-dialog"> + <h3>delete creation "<span id="delete-creation-title"></span>"?</h3> + <br> + <form method="dialog"> + <button>no</button> + <button id="delete-creation-confirm">yes</button> + </form> + </dialog> </div> </body> @@ -1,3 +1,3 @@ <svg xmlns="http://www.w3.org/2000/svg" width="32" height="32"> -<path d="M6 6 L26 6 M6 16 L26 16 M6 26 L26 26" stroke="#88f" stroke-width="4" stroke-linecap="round"/> +<path d="M16 4 L16 28 M16 4 l -7 6 m 7 -6 l 7 6 M16 28 l -7 -6 m 7 6 l 7 -6" stroke="#88f" stroke-width="4" stroke-linecap="round"/> </svg> @@ -1,10 +1,5 @@ 'use strict'; -/* -TODO: -- multiple creations -*/ - const APP_ID = 'dh3YgVZQdX1Q'; function generate_creation_id() { @@ -2357,6 +2352,7 @@ function export_widgets_to_local_storage() { localStorage.setItem(`${APP_ID}-${creation_id}-description`, widget_str); creation_metadata[creation_id] = { lastViewed: Date.now(), + title: get_creation_title(), }; localStorage.setItem(`${APP_ID}-metadata`, JSON.stringify(creation_metadata)); } @@ -2370,13 +2366,37 @@ function load_creation(id) { const result = import_widgets( localStorage.getItem(`${APP_ID}-${id}-description`) ); - if (result.error) return result; - return true; + if (result.error) { + show_error(result.error); + } } function new_creation() { creation_id = generate_creation_id(); - return import_widgets(null); + const result = import_widgets(null); + if (result.error) { + show_error(result.error); + } +} + +function load_most_recent_or_create_new() { + let load = undefined; + if (creation_metadata) { + // load creation with largest lastViewed time + for (const id in creation_metadata) { + if ( + !load || + creation_metadata[id].lastViewed > creation_metadata[load].lastViewed + ) { + load = id; + } + } + } + if (load) { + load_creation(load); + } else { + new_creation(); + } } function get_shader_source() { @@ -2501,6 +2521,58 @@ function startup() { document.getElementById('about-dialog').showModal(); }); + document.getElementById('list-creations').addEventListener('click', () => { + const container = document.getElementById('creations'); + container.innerHTML = ''; + const creations_dialog = document.getElementById('creations-dialog'); + creations_dialog.showModal(); + for (const id in creation_metadata) { + const metadata = creation_metadata[id]; + const entry = document.createElement('div'); + entry.classList.add('creation-entry'); + const title = document.createElement('h4'); + title.classList.add('creation-entry-title'); + title.appendChild(document.createTextNode(metadata.title)); + entry.appendChild(title); + const lastViewed = document.createElement('div'); + lastViewed.classList.add('creation-entry-last-viewed'); + lastViewed.appendChild( + document.createTextNode( + 'Last viewed: ' + new Date(metadata.lastViewed).toLocaleString() + ) + ); + entry.appendChild(lastViewed); + entry.addEventListener('click', () => { + load_creation(id); + creations_dialog.close(); + }); + container.appendChild(entry); + } + }); + + document.getElementById('delete-creation').addEventListener('click', () => { + document.getElementById('delete-creation-title').innerText = + get_creation_title(); + document.getElementById('delete-dialog').showModal(); + }); + + document + .getElementById('delete-creation-confirm') + .addEventListener('click', () => { + delete creation_metadata[creation_id]; + localStorage.removeItem(`${APP_ID}-${creation_id}-description`); + localStorage.setItem( + `${APP_ID}-metadata`, + JSON.stringify(creation_metadata) + ); + creation_id = undefined; + load_most_recent_or_create_new(); + }); + + document.getElementById('new-creation').addEventListener('click', () => { + new_creation(); + }); + document.getElementById('resolution-form').addEventListener('submit', () => { render_width = resolution_x_element.value; render_height = resolution_y_element.value; @@ -2654,26 +2726,7 @@ void main() { }); creation_metadata = parse_json(localStorage.getItem(`${APP_ID}-metadata`)); - let result; - if (creation_metadata) { - // load creation with largest lastViewed time - let load = undefined; - for (const id in creation_metadata) { - if ( - !load || - creation_metadata[id].lastViewed > creation_metadata[load].lastViewed - ) { - load = id; - } - } - result = load_creation(load); - } else { - creation_metadata = {}; - result = new_creation(); - } - if (result.error) { - show_error(result); - } + load_most_recent_or_create_new(); frame(0.0); @@ -1,5 +1,6 @@ :root { --color-text: #ddd; + --color-link: #8fc; } body { @@ -15,7 +16,7 @@ dialog { a, a:visited { - color: #8fc; + color: var(--color-link); } h1, @@ -219,7 +220,7 @@ input[type='checkbox'] { summary { cursor: pointer; } -#title { +#top-area { vertical-align: middle; font-weight: bold; font-size: 0.5cm; @@ -227,6 +228,9 @@ summary { #title-icon { height: 1cm; } +#creation-buttons { + margin-top: 0.2em; +} #resolution-form input[type='number'] { width: 4em; } @@ -326,3 +330,21 @@ th { margin: 0; padding: 0.2em; } + +.creation-entry { + cursor: pointer; + border-bottom: 2px solid white; + padding: 6px; +} + +.creation-entry:hover { + background: #fff4; +} + +.creation-entry-title { + color: var(--color-link); +} + +.creation-entry-last-viewed { + font-style: italic; +} |