]> git.cworth.org Git - zombocom-ai/blobdiff - index.html
Reword Coda's final message
[zombocom-ai] / index.html
index b7b82de7068bedb0c4b3f1910ee11c2e78c2867d..8db8b695b93b68c2187af45978e1fe4e8a07e6c0 100644 (file)
@@ -5,7 +5,7 @@
   <meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
   <title>ZOMBO</title>
   <link href="/zombo.css" rel="stylesheet" type="text/css">
-  <meta name="viewport" content="width=device-width,initial-scale=1,maximum-scale=1,user-scalable=no">
+  <meta name="viewport" content="width=device-width,initial-scale=1">
   <meta http-equiv="X-UA-Compatible" content="IE=edge,chrome=1">
   <meta name="HandheldFriendly" content="true">
 </head>
     </div>
 
     <p>
-      Welcome to Zombocom. You can do anything at Zombcom, anything at
+      Welcome to Zombocom. You can do anything at Zombocom, anything at
       all. The only limit is yourself!
     </p>
 
+    <dialog id="name-dialog">
+      <form method="dialog">
+        <p>
+          <label>Your name:
+            <input id="name" type="text" autocomplete="off">
+          </label>
+        </p>
+        <div>
+          <button value="default">OK</button>
+        </div>
+      </form>
+    </dialog>
+
     <p>
+      <div id="spinner" align="center">
+        <div class="animate-flicker">
+          <p>
+            <img src="/pngwheel.png" class="rotate thefade">
+          </p>
+        </div>
+      </div>
+
       <form action="" id="zombo-form">
         <div class="form-row large">
           <label for="prompt">
-            What do you imagine?
+            What can you imagine?
           </label>
-          <textarea id="prompt" rows="4" width="100%" autocomplete="off" required>
-          </textarea>
+          <button id="safety" type="button">Safety prompt</button>
+          <textarea id="prompt" rows="4" width="100%" autocomplete="off" required></textarea>
         </div>
 
         <div class="form-row small left">
-          <label for="code">
-            Numeric code
-          </label>
-          <input id="code" type="text" size="10" autocomplete="off" placeholder="(Chosen randomly)" />
-        </div>
-
-        <div class="form-row small right">
-          <button id="safety" class="right" type="button">Safety prompt</button>
-          <script>
-            const prompt = document.querySelector("#prompt");
-            const safety= document.querySelector("#safety");
-            // TODO: Dynamically generate many different prompts here
-            safety.addEventListener("click", () => {
-                prompt.value = "Matte painting of a Samurai warrior";
-                return false;
-            })
-          </script>
+          <div class="labeled-row">
+            <label for="code">
+              Numeric code:
+            </label>
+            <input id="code" type="number" min="0" max="4294967295" autocomplete="off" placeholder="(Leave blank for random)" />
+          </div>
         </div>
 
         <div class="form-row large">
       </form>
     </p>
 
-    <p>
-      <form action="" id="comment-form">
-        <input id="comment" type="text" style="width:100%" autocomplete="off" placeholder="Add a comment" />
-      </form>
-    </p>
-
-    <div align="center">
-      <div class="animate-flicker">
-        <p>
-          <img src="/pngwheel.png" class="rotate thefade">
-        </p>
-      </div>
+    <div id="images">
     </div>
 
     <audio loop="" src="/zombo_words.mp3" type="audio/mpeg"></audio>
-    <button id="mute" class="fade volume">
+    <button id="mute" class="menu-button fade volume">
       <div>🔊</div>
       <script>
 const mute = document.querySelector("#mute");
@@ -101,22 +100,258 @@ mute.addEventListener("click", () => {
 
     </button>
 
+    <button id="profile" class="menu-button">
+      <div>👤</div>
+    </button>
+
   </div>
 
   <script src="/socket.io/socket.io.js"></script>
   <script>
     var socket = io();
 
-    var form = document.querySelector("#comment-form");
-    var comment = document.querySelector("#comment");
+    const name_input = document.querySelector("#name");
+    const name_dialog = document.querySelector("#name-dialog");
+    var informed_name;
+    const images = document.querySelector("#images");
+    const zombo_form = document.querySelector("#zombo-form");
+    const prompt = document.querySelector("#prompt");
+    const code = document.querySelector("#code");
+    const safety= document.querySelector("#safety");
+    const spinner = document.querySelector("#spinner");
+    const profile = document.querySelector("#profile");
+    var spinner_timeout;
 
-    form.addEventListener('submit', function(e) {
-        e.preventDefault();
-        if (comment.value) {
-            socket.emit('comment', comment.value);
-            comment.value = '';
+    profile.addEventListener('click', () => {
+        name_dialog.showModal();
+    });
+
+    name_dialog.addEventListener('close', () => {
+        socket.emit('set-name', name_input.value);
+    });
+
+    function add_comment(comments, comment) {
+        const dt = document.createElement('dt');
+        const dd = document.createElement('dd');
+        dt.textContent = comment.name + ':';
+        dd.textContent = comment.text;
+        comments.appendChild(dt);
+        comments.appendChild(dd);
+    }
+
+    // When we enter the endgame, we disable the art-generation form,
+    // (just hide it)
+    socket.on('endgame', () => {
+       zombo_form.style.display = "none";
+    });
+
+    socket.on('comment', function(comment) {
+        const comments = document.querySelector("#comments_" + comment.image_id);
+        add_comment(comments, comment);
+    });
+
+    socket.on('inform-name', (name) => {
+        console.log("Received inform-name event: " + name);
+
+        /* When we receive a name we store it in 3 places:
+         *
+         *   * The informed_name variable (confirming what the server knows)
+         *   * The name_input field (so the user will see that in their profile)
+         *   * In localStorage (for use in a future session)
+         */
+        informed_name = name;
+        name_input.value = name;
+        localStorage.setItem('name', name);
+    });
+
+    socket.on('reset', () => {
+        images.replaceChildren();
+
+        /* Since the server is seeing us for the first time, let it
+           know our name (if we have one). */
+        const name = localStorage.getItem('name');
+        if (name) {
+            socket.emit('set-name', name);
+            return;
         }
     });
+
+    socket.on('image', (image) => {
+        const figure = document.createElement('figure');
+        figure.id = "image_" + image.id;
+
+        const img = document.createElement('img');
+        img.src = image.filename;
+
+        if (image.link) {
+            const a = document.createElement('a');
+            a.href = image.link;
+            a.appendChild(img);
+            figure.appendChild(a);
+        } else {
+            figure.appendChild(img);
+        }
+
+        if (image.censored) {
+            img.style.display = "none";
+        }
+
+        if (image.prompt && image.code) {
+            const figcaption = document.createElement('figcaption');
+            const caption_text = document.createTextNode(`${image.prompt} (${image.code}) `);
+            figcaption.appendChild(caption_text);
+
+            const reuse_button = document.createElement('button');
+            reuse_button.appendChild(document.createTextNode("Reuse"));
+            figcaption.appendChild(reuse_button);
+
+            reuse_button.addEventListener('click', () => {
+                prompt.value = image.prompt;
+                window.scrollTo(0,0);
+            });
+
+            if (image.censored) {
+                figcaption.style.display = "none";
+            }
+
+            figure.appendChild(figcaption);
+        }
+
+        const dl_comments = document.createElement('dl');
+        dl_comments.className = "comments";
+        dl_comments.id = "comments_" + image.id;
+
+        image.comments.forEach((comment) => {
+            add_comment(dl_comments, comment);
+        });
+
+        figure.appendChild(dl_comments);
+
+        const comment_form = document.createElement('form');
+        const comment_input = document.createElement('input')
+        comment_input.type = "text";
+        comment_input.className = "comment";
+        comment_input.placeholder = "Add a comment";
+        comment_form.appendChild(comment_input);
+        figure.appendChild(comment_form);
+
+        comment_input.addEventListener('focus', () => {
+            /* If the server has informed us it has our name, we are done. */
+            if (informed_name)
+                return;
+
+            /* If server has no name, check local storage. */
+            const name = localStorage.getItem('name');
+            if (name) {
+                socket.emit('set-name', name);
+                return;
+            }
+
+            /* Failing both, bring up the modal dialog to set the name. */
+            name_dialog.showModal();
+        });
+
+        comment_form.addEventListener('submit', function(e) {
+            e.preventDefault();
+            if (comment_input.value) {
+                socket.emit('comment', {image_id: image.id,
+                                        text: comment_input.value});
+                comment_input.value = '';
+            }
+        });
+
+        images.prepend(figure);
+    });
+
+    function hide_spinner() {
+        zombo_form.style.display = "grid";
+        spinner.style.display = "none";
+    }
+
+    zombo_form.addEventListener('submit', function(e) {
+        e.preventDefault();
+        /* Hide the form and show spinner while generation is happening. */
+        zombo_form.style.display = "none";
+        spinner.style.display = "block";
+        spinner_timeout = setTimeout(hide_spinner, 60000);
+        socket.emit('generate', {"prompt": prompt.value, "code": code.value});
+        prompt.value = '';
+    });
+
+    socket.on('generation-done', () => {
+        /* Re-display the form and hide spinner now that generation is over. */
+        clearTimeout(spinner_timeout);
+        hide_spinner();
+    });
+
+    function random_from(items) {
+        return items[Math.floor(Math.random()*items.length)];
+    }
+
+    safety.addEventListener("click", () => {
+        const art_type = [
+            "A portrait of",
+            "A hyperrealistic photograph of",
+            "A matte painting of",
+            "Epic fantasy card art of",
+            "Professional oil painting of",
+            "An image of",
+            "A pencil sketch of",
+            "A watercolor of",
+            "A 3D rendering of",
+            "A marble statue of",
+        ];
+        const subject = [
+            " a modern home",
+            " crashing waves",
+            " a Porsche 911 Carrera",
+            " a Halo spartan",
+            " a cute cat",
+            " a mad scientist",
+            " an elfin princess",
+            " sci-fi buildings",
+            " pastel purple clouds",
+            " a Teenage Mutant Ninja Turtle",
+            " Pikachu",
+        ];
+        const scenery = [
+            " in tropical surroundings",
+            " in space",
+            " in an ocean storm",
+            " in a snowy forest",
+            " in a cardboard box",
+            " holding an axe",
+            " in an epic landscape",
+            " in a haunted forest",
+            " riding a motorbike",
+            " in a futuristic city at night",
+            " in a dystopian landscape, foggy",
+            " in the land of snow",
+            " that looks like a watermelon",
+            " on the streets of London at night with neon lights flashing",
+            " that is part octopus",
+            " melting into a puddle",
+            " on a birthday cake",
+        ];
+        const artist = [
+            ", unreal engine 5",
+            ", concept art",
+            ", graphic novel",
+            " by Vincent Van Gogh",
+            " by Claude Monet",
+            " by Johannes Vermeer",
+            ", fantasy art, neon fog",
+            ", epic lighting from above",
+            ", trending on artstation",
+            " by Gustav Klimt",
+            " by Leonardo da Vinci",
+        ];
+
+        prompt.value = random_from(art_type) + random_from(subject) +
+            random_from(scenery) + random_from(artist);
+        return false;
+    });
+
   </script>
 </body>
 </html>