nwf-mii-cemu-toy frontend mockup

unlocalized and not up to date, moved to playcode for this to be used with https://github.com/ariankordi/nwf-mii-cemu-toy

by arian_

HTML

<!doctype html>
<html lang="en">

<head>
    <title>Mii Renderer (REAL)</title>
    <link rel="stylesheet" href="assets/style.css">
    <meta name="viewport" content="width=device-width,initial-scale=1">
</head>

<body class="dark">
    <h1>Mii Renderer (REAL)</h1>
    <!-- GET is default for forms anyway but barely anyone remembers that
    so this is being specified manually too for readability purposes yes. -->
    <form action="https://debian.local:8443/render.png" method="GET">
        <label for="input_type">Mii input type:</label>
        <!-- only useful for backend when you are not using js bc js will disable the inputs -->
        <select id="input_type" name="input_type">
            <option value="nnid" selected>Nintendo Network ID</option>
            <!-- default -->
            <option value="data">
                Mii data (Base64 or STUDIO CODE TBD)
            </option>
            <option value="file">
                Wii U FFSD File (TBD NEED POST REQUEST)
            </option>
            <option value="qrcode">Scan QR code (TBD)</option>
            <option value="amiibo">Amiibo data (TBD)</option>
        </select>
        <br>
        <div id="file-group">
            <input type="file" name="file" id="file"><br>
            <label class="small" for="file">(96 byte FFLStoreData Mii binary format)</label>
            <div>
                (TODO TODO you need to VERIFY THE LENGTH, and the CRC16 of
                the file. AND the base64. AND convert to POST. THIS SUCKS)
            </div>
        </div>
        <div id="qrcode-group">
            <button type="button">From camera</button>
            <button type="button">Select file or photo</button>
            <p style="color: red">
                THIS IS NOT IMPLEMENTED AND WILL NOT WORK. IT WILL NOT DO
                ANYTHING. DO NOT TRY IT BECAUSE IT WILL DO NOTHING. SEGGS.
                P*RN. AAAAAAAAAA
            </p>
            <input type="hidden" name="qrcode" id="qrcode">
...

CSS

/* automatic dark mode */
@media (prefers-color-scheme: dark) {
  body {
    color: white;
    background-color: black;
  }
}

/* manual dark mode */
.dark {
  color: white;
  background-color: black;
}

body {
  /*font-family: sans-serif;
  */
  font-family: -apple-system, BlinkMacSystemFont,
    'Segoe UI', Roboto, Helvetica,
    Arial, sans-serif;

  line-height: 150%;
  text-align: center;
}
.small {
  font-size: 12px;
}
#results {
  list-style-type: none;
  padding: 0;
}
ul {
  list-style-position: inside;
}
#results > li {
  margin: 0 auto 5px;
  padding: 5px;
}
#results img {
  border-radius: 5px;
  /*max-width: calc(100vw - 32px);
  */max-width: 100%;
  border: 1px solid #808080;
}
.short-number {
  width: 45px;
}
.load-error {
  color: red;
  border-radius: 5px;
  max-width: 40vw;
  border: 1px solid red;
}
.long-field {
  width: 30em;
}
/* for pattern attribute */
.long-field:required:invalid:not(:placeholder-shown) {
  background-color: lightpink;
}

.fade-in {
  opacity: 0;
  animation: fadeInAnimation cubic-bezier(0.165, 0.840, 0.440, 1.000) 0.4s;
  animation-fill-mode: forwards;
}

@keyframes fadeInAnimation {
  from { opacity: 0; }
  to { opacity: 1; }
}
/*
.fade-in {
  opacity: 0;
  transform: translateY(-100%) translateX(0);
  animation: slideInFrom 250ms cubic-bezier(0.165, 0.840, 0.440, 1.000) 0ms forwards;
}
@keyframes slideInFrom{ to {  transform: unset; opacity: unset; } }
*/

JavaScript

// Select elements based on their names and ids
var resolutionNumber = document.getElementsByName('width')[0];
var widthSlider = document.getElementById('resolution-slider');
var bgColor = document.getElementsByName('bgColor')[0];
var transparentCheckbox = document.getElementById('transparent-checkbox');

var bgDefault = '#00ff00'//bgColor.value;

// Update the width slider when the resolution number is changed
resolutionNumber.addEventListener('input', function() {
    widthSlider.value = this.value;
});

// Update the resolution number when the width slider is changed
widthSlider.addEventListener('input', function() {
    resolutionNumber.value = this.value;
});

// When the transparent-checkbox is checked, change the background color to #00ff00
transparentCheckbox.addEventListener('change', function() {
    if(this.checked) {
        bgColor.value = bgDefault;
        this.disabled = true;
    } else if(bgColor.value === bgDefault) {
        // TODO: you may consider changing bg by one
        // so you can still have a green background
        this.checked = true;
        this.disabled = true;
    }
});

// When the background color is changed to #00ff00, check the transparent-checkbox
// Note: This also unchecks the checkbox if the color is changed to anything other than #00ff00
bgColor.addEventListener('input', function() {
    if(this.value.toLowerCase() === bgDefault) {
        transparentCheckbox.checked = true;
        transparentCheckbox.disabled = true;
    } else {
        transparentCheckbox.checked = false;
        transparentCheckbox.disabled = false;
    }
});

var scaleInput = document.getElementsByName('scale')[0];
var realMax = 1080;
// Function to update max resolution based on scale
function updateMaxResolution() {
    var scale = parseInt(scaleInput.value);
    var maxResolution = realMax / scale;

    // Adjust current values if they exceed the new max
    if(widthSlider.value > maxResolution) {
        widthSlider.value = maxResolution;
 ...