From 6c7b06f021f358c66c0adfbf13d8cd7e5e59a8a4 Mon Sep 17 00:00:00 2001 From: meeg_leeto Date: Sat, 30 Apr 2022 01:36:15 +0100 Subject: [PATCH] feat: HTTP interface fully functional --- data/served/index.html | 7 ++--- data/served/main.css | 56 +++++++++++++++++++++++++++++++++++++++ data/served/main.js | 50 ++++++++++++++++++++++++---------- data/served/reset.min.css | 1 + 4 files changed, 97 insertions(+), 17 deletions(-) create mode 100644 data/served/reset.min.css diff --git a/data/served/index.html b/data/served/index.html index da213df..8ad46e1 100644 --- a/data/served/index.html +++ b/data/served/index.html @@ -6,6 +6,7 @@ Lonk + @@ -19,12 +20,12 @@ be browsing the web with Javascript blocked, then just do a POST request to /shorten with the URL you wish to shorten Base64-encoded as the body. --> -
- + +
-

+

\ No newline at end of file diff --git a/data/served/main.css b/data/served/main.css index e69de29..903dd42 100644 --- a/data/served/main.css +++ b/data/served/main.css @@ -0,0 +1,56 @@ +body { + background-color: #0b0b0e; + + width: 100vw; + min-height: 100vh; + height: 1px; + + box-sizing: border-box; + padding-top: 5vh; + padding-bottom: 5vh; + + display: flex; + flex-flow: column nowrap; + align-items: center; + justify-content: space-between; +} + +#form { + width: 95%; +} + +#form > input { + width: 100%; + + background-color: transparent; + color: #ffab3e; + text-align: center; + font-family: monospace; + + border: none; + border-bottom: #15151b; +} + +#shortened { + font-size: calc(min(20pt, 10vw)); + font-family: monospace; + color: #385d22; + text-align: center; +} + +#info { + font-family: monospace; + color: rgb(91, 91, 91); + text-align: center; +} + +#info[state="hidden"] { + display: none; +} +#info[state~="hidden"] { + display: block; +} + +#info[state="error"] { + color: rgb(142, 49, 33); +} \ No newline at end of file diff --git a/data/served/main.js b/data/served/main.js index 6332e1c..e3e60e3 100644 --- a/data/served/main.js +++ b/data/served/main.js @@ -2,19 +2,21 @@ (() => { document.addEventListener('DOMContentLoaded', (_) => { - const waiting = false; + let waiting = false; let xhr; + const shortened = document.getElementById('shortened'); + const info = document.getElementById('info'); const field = document.getElementById('url'); - - field.addEventListener('change', () => { - if (waiting && xhr != null) { - xhr.abort(); - } - }); - const form = document.getElementById('form'); + // Select the full link with one click + shortened.onclick = () => { + this.focus(); + this.select(); + }; + + // Set up the actual submission form.addEventListener('submit', (event) => { // We need to create a different body, so prevent the default submission. event.preventDefault(); @@ -25,7 +27,12 @@ } // Get the URL the user is trying to shorten. - const url = document.getElementById('url').value; + let url = document.getElementById('url').value; + + // If it doesn't have a protocol, assume https. + if (!/^\w+:\/\/.*$/.test(url)) { + url = 'https://' + url; + } // Encode the URL as Base64. const encoded = btoa(encodeURIComponent(url).replace(/%([0-9A-F]{2})/g, (match, p1) => @@ -38,18 +45,33 @@ xhr.overrideMimeType('text/plain'); xhr.send(encoded); xhr.onload = () => { + waiting = false; switch (xhr.status) { case 200: let slug = xhr.response; - console.log(slug); - break; + const short_link = `${window.location.href}l/${slug}`; + + // Display to the user + + shortened.innerText = short_link; + + info.setAttribute('state', 'info'); + info.innerText = 'Link successfully shortened and copied to your clipboard.'; + + // Copy the link to the clipboard + + navigator.clipboard.writeText(short_link); + break; default: - console.log(xhr.response); - break; + info.setAttribute('state', 'error'); + info.innerText = xhr.response; + break; } }; xhr.onerror = () => { - // TODO + waiting = false; + info.setAttribute('state', 'error'); + info.innerText = "Failed to shorten the URL. Please try again."; }; }); }); diff --git a/data/served/reset.min.css b/data/served/reset.min.css new file mode 100644 index 0000000..28c78d2 --- /dev/null +++ b/data/served/reset.min.css @@ -0,0 +1 @@ + html, body, div, span, applet, object, iframe, h1, h2, h3, h4, h5, h6, p, blockquote, pre, a, abbr, acronym, address, big, cite, code, del, dfn, em, img, ins, kbd, q, s, samp, small, strike, strong, sub, sup, tt, var, b, u, i, center, dl, dt, dd, ol, ul, li, fieldset, form, label, legend, table, caption, tbody, tfoot, thead, tr, th, td, article, aside, canvas, details, embed, figure, figcaption, footer, header, hgroup, menu, nav, output, ruby, section, summary, time, mark, audio, video {margin: 0;padding: 0;border: 0;font-size: 100%;font: inherit;vertical-align: baseline;}:focus {outline: 0;}article, aside, details, figcaption, figure, footer, header, hgroup, menu, nav, section {display: block;}body {line-height: 1;}ol, ul {list-style: none;}blockquote, q {quotes: none;}blockquote:before, blockquote:after, q:before, q:after {content: '';content: none;}table {border-collapse: collapse;border-spacing: 0;}input[type=search]::-webkit-search-cancel-button, input[type=search]::-webkit-search-decoration, input[type=search]::-webkit-search-results-button, input[type=search]::-webkit-search-results-decoration {-webkit-appearance: none;-moz-appearance: none;}input[type=search] {-webkit-appearance: none;-moz-appearance: none;-webkit-box-sizing: content-box;-moz-box-sizing: content-box;box-sizing: content-box;}textarea {overflow: auto;vertical-align: top;resize: vertical;}audio, canvas, video {display: inline-block;*display: inline;*zoom: 1;max-width: 100%;}audio:not([controls]) {display: none;height: 0;}[hidden] {display: none;}html {font-size: 100%;-webkit-text-size-adjust: 100%;-ms-text-size-adjust: 100%;}a:focus {outline: thin dotted;}a:active, a:hover {outline: 0;}img {border: 0;-ms-interpolation-mode: bicubic;}figure {margin: 0;}form {margin: 0;}fieldset {border: 1px solid #c0c0c0;margin: 0 2px;padding: 0.35em 0.625em 0.75em;}legend {border: 0;padding: 0;white-space: normal;*margin-left: -7px;}button, input, select, textarea {font-size: 100%;margin: 0;vertical-align: baseline;*vertical-align: middle;}button, input {line-height: normal;}button, select {text-transform: none;}button, html input[type="button"], input[type="reset"], input[type="submit"] {-webkit-appearance: button;cursor: pointer;*overflow: visible;}button[disabled], html input[disabled] {cursor: default;}input[type="checkbox"], input[type="radio"] {box-sizing: border-box;padding: 0;*height: 13px;*width: 13px;}input[type="search"] {-webkit-appearance: textfield;-moz-box-sizing: content-box;-webkit-box-sizing: content-box;box-sizing: content-box;}input[type="search"]::-webkit-search-cancel-button, input[type="search"]::-webkit-search-decoration {-webkit-appearance: none;}button::-moz-focus-inner, input::-moz-focus-inner {border: 0;padding: 0;}textarea {overflow: auto;vertical-align: top;}table {border-collapse: collapse;border-spacing: 0;}html, button, input, select, textarea {color: #222;}::-moz-selection {background: #b3d4fc;text-shadow: none;}::selection {background: #b3d4fc;text-shadow: none;}img {vertical-align: middle;}fieldset {border: 0;margin: 0;padding: 0;}textarea {resize: vertical;}.chromeframe {margin: 0.2em 0;background: #ccc;color: #000;padding: 0.2em 0;} \ No newline at end of file