implemented esbuild and cleaned up stuff

cobalt should now load even faster
This commit is contained in:
wukko
2022-07-30 15:01:54 +06:00
parent f6b0894def
commit 22c16b2fc8
36 changed files with 31 additions and 70 deletions

499
src/front/cobalt.css Normal file
View File

@@ -0,0 +1,499 @@
:root {
--transparent: rgba(0, 0, 0, 0);
--without-padding: calc(100% - 4rem);
--border-15: 0.15rem solid var(--accent);
}
@media (prefers-color-scheme: dark) {
:root {
--accent: rgb(225, 225, 225);
--accent-hover: rgb(20, 20, 20);
--accent-press: rgb(10, 10, 10);
--accent-unhover: rgb(100, 100, 100);
--accent-unhover-2: rgb(110, 110, 110);
--background: rgb(0, 0, 0);
}
}
@media (prefers-color-scheme: light) {
:root {
--accent: rgb(25, 25, 25);
--accent-hover: rgb(230 230 230);
--accent-press: rgb(240 240 240);
--accent-unhover: rgb(190, 190, 190);
--accent-unhover-2: rgb(110, 110, 110);
--background: rgb(255, 255, 255);
}
}
[data-theme="dark"] {
--accent: rgb(225, 225, 225);
--accent-hover: rgb(20, 20, 20);
--accent-press: rgb(10, 10, 10);
--accent-unhover: rgb(100, 100, 100);
--accent-unhover-2: rgb(110, 110, 110);
--background: rgb(0, 0, 0);
}
[data-theme="light"] {
--accent: rgb(25, 25, 25);
--accent-hover: rgb(230 230 230);
--accent-press: rgb(240 240 240);
--accent-unhover: rgb(190, 190, 190);
--accent-unhover-2: rgb(110, 110, 110);
--background: rgb(255, 255, 255);
}
html,
body {
margin: 0;
background: var(--background);
color: var(--accent);
font-family: 'Noto Sans Mono', 'Consolas', 'SF Mono', monospace;
user-select: none;
-webkit-tap-highlight-color: var(--transparent);
overflow: hidden;
-ms-overflow-style: none;
scrollbar-width: none;
}
a {
color: var(--accent);
text-decoration: none;
}
::placeholder {
color: var(--accent-unhover-2);
}
::-webkit-scrollbar {
display: none;
}
:focus-visible {
outline: var(--border-15);
}
[type=checkbox] {
margin-right: 0.8rem;
}
[type="checkbox"] {
-webkit-appearance: none;
margin-right: 0.8rem;
z-index: 0;
}
[type="checkbox"]::before {
content: "";
width: 15px;
height: 15px;
border: var(--border-15);
background-color: var(--background);
display: block;
z-index: 5;
position: relative;
}
[type="checkbox"]:checked::before {
box-shadow: inset 0 0 0 0.2rem var(--background);
background-color: var(--accent);
}
button {
background: none;
border: none;
font-family: 'Noto Sans Mono', 'Consolas', 'SF Mono', monospace;
color: var(--accent);
font-size: 0.9rem;
}
input,
input[type="text"],
[type="text"] {
border-radius: 0;
}
button:hover,
.switch:hover,
.checkbox:hover,
.text-to-copy:hover {
background: var(--accent-hover);
cursor: pointer;
}
.switch.text-backdrop:hover,
.switch.text-backdrop:active,
.text-to-copy.text-backdrop:hover,
.text-to-copy.text-backdrop:active {
background: var(--accent);
color: var(--background);
}
button:active,
.switch:active,
.checkbox:active,
.text-to-copy:active {
background: var(--accent-press);
cursor: pointer;
}
input[type="checkbox"] {
cursor: pointer;
}
.button {
background: none;
border: var(--border-15);
color: var(--accent);
padding: 0.3rem 0.75rem 0.5rem;
font-size: 1rem;
}
.mono {
font-family: 'Noto Sans Mono', 'Consolas', 'SF Mono', monospace;
}
.center {
top: 50%;
left: 50%;
transform: translate(-50%, -50%);
}
#cobalt-main-box {
position: fixed;
width: 60%;
height: auto;
display: inline-flex;
padding: 3rem;
}
#logo-area {
padding-right: 3rem;
padding-top: 0.1rem;
text-align: left;
font-size: 1rem;
white-space: nowrap;
}
#download-area {
display: inline-flex;
height: 2rem;
width: 100%;
margin-top: -0.6rem;
}
.box {
background: var(--background);
border: var(--border-15);
color: var(--accent);
}
#url-input-area {
background: var(--background);
padding: 1.2rem 1rem;
width: 100%;
color: var(--accent);
border: 0;
float: right;
border-bottom: 0.1rem solid var(--accent-unhover);
transition: border-bottom 0.2s;
outline: none;
}
#url-input-area:focus {
outline: none;
border-bottom: 0.1rem solid var(--accent);
}
#download-button {
height: 2.5rem;
color: var(--accent);
background: none;
border: none;
font-size: 1.4rem;
cursor: pointer;
padding: 0;
letter-spacing: -0.1rem;
}
#download-button:disabled {
color: var(--accent-unhover);
cursor: not-allowed;
}
#footer {
bottom: 0rem;
position: absolute;
left: 50%;
transform: translate(-50%, -50%);
font-size: 0.9rem;
text-align: center;
width: 90%;
}
.footer-button {
cursor: pointer;
color: var(--accent-unhover-2);
border: 0.15rem var(--accent-unhover-2) solid;
padding: 0.4rem 0.8rem 0.5rem;
margin-bottom: 0.5rem;
}
.footer-button:hover {
color: var(--accent);
border: var(--border-15);
}
.text-backdrop {
background: var(--accent);
color: var(--background);
padding: 0 0.1rem;
}
::-moz-selection {
background-color: var(--accent);
color: var(--background);
}
::selection {
background-color: var(--accent);
color: var(--background);
}
.popup {
visibility: hidden;
position: fixed;
height: auto;
width: 30%;
z-index: 999;
padding: 3rem 2rem 2rem 2rem;
font-size: 0.9rem;
max-height: 80%;
}
#popup-backdrop {
opacity: 0.5;
background-color: var(--background);
position: fixed;
top: 0;
left: 0;
width: 100%;
height: 100%;
z-index: 998;
}
.popup.scrollable {
height: 80%;
}
.scrollable .bottom-link {
padding-bottom: 2rem;
}
.nowrap {
white-space: nowrap;
}
.about-padding {
padding-bottom: 1.5rem;
}
.popup-subtitle {
font-size: 1.1rem;
padding-bottom: 0.5rem;
}
.little-subtitle {
font-size: 1.05rem;
}
.popup-desc {
width: 100%;
text-align: left;
float: left;
line-height: 1.7rem;
}
.popup-title {
font-size: 1.5rem;
margin-bottom: 0.5rem;
line-height: 1.85em;
}
.popup-footer {
bottom: 0;
position: fixed;
margin-bottom: 1.5rem;
background: var(--background);
width: var(--without-padding);
}
.popup-footer-content {
font-size: 0.8rem;
line-height: 1.7rem;
color: var(--accent-unhover-2);
border-top: 0.05rem solid var(--accent-unhover-2);
padding-top: 0.4rem;
}
.popup-above-title {
color: var(--accent-unhover-2);
font-size: 0.8rem;
}
.popup-content {
overflow-x: hidden;
overflow-y: auto;
height: var(--without-padding);
scrollbar-width: none;
}
.popup-header {
position: relative;
background: var(--background);
z-index: 999;
}
.popup-content.with-footer {
margin-bottom: 3rem;
}
#close {
cursor: pointer;
float: right;
right: 0rem;
position: absolute;
}
.settings-category {
padding-bottom: 1.2rem;
}
.title {
width: 100%;
text-align: left;
line-height: 1.7rem;
color: var(--accent-unhover-2);
border-bottom: 0.05rem solid var(--accent-unhover-2);
padding-bottom: 0.25rem;
}
.bottom-margin {
margin-bottom: 1rem;
}
.checkbox {
display: inline-flex;
align-items: center;
flex-direction: row;
flex-wrap: nowrap;
align-content: center;
padding: 0.6rem;
padding-right: 1rem;
border: 0.1rem solid;
width: auto;
margin: 0 0.5rem 0.5rem 0;
}
.checkbox-label {
line-height: 1.3rem;
}
.switch-container {
width: 100%;
}
.subtitle {
width: 100%;
text-align: left;
line-height: 1.7rem;
padding-bottom: 0.4rem;
color: var(--accent);
margin-top: 1rem;
}
.small-padding .subtitle {
margin-top: 0.5rem;
}
.explanation {
padding-top: 1rem;
width: 100%;
font-size: 0.8rem;
text-align: left;
line-height: 1.3rem;
color: var(--accent-unhover-2);
}
.switch {
border-top: solid 0.1rem var(--accent);
border-bottom: solid 0.1rem var(--accent);
padding: 0.8rem;
width: 100%;
text-align: center;
color: var(--accent);
background: var(--background);
display: grid;
align-items: center;
cursor: pointer;
}
.switch.full {
border: solid 0.1rem var(--accent);
}
.switch.left {
border-left: solid 0.1rem var(--accent);
}
.switch.right {
border-right: solid 0.1rem var(--accent);
}
.switch.space-right {
margin-right: 1rem
}
.switch[data-enabled="true"] {
color: var(--background);
background: var(--accent);
cursor: default;
}
.switches {
display: flex;
width: auto;
flex-direction: row;
flex-wrap: nowrap;
}
.text-to-copy {
user-select: text;
border: var(--border-15);
padding: 1rem;
overflow: auto;
}
/* adapt the page according to screen size */
@media screen and (min-width: 2300px) {
html {
zoom: 130%;
}
}
@media screen and (min-width: 3840px) {
html {
zoom: 180%;
}
}
@media screen and (min-width: 5000px) {
html {
zoom: 300%;
}
}
@media screen and (max-width: 1440px) {
#cobalt-main-box {
width: 65%;
}
.popup {
width: 40%;
}
}
@media screen and (max-width: 1024px) {
#cobalt-main-box {
width: 75%;
}
.popup {
width: 60%;
}
}
@media screen and (max-height: 850px) {
.popup {
height: 80%
}
.bottom-link {
padding-bottom: 2rem;
}
}
/* mobile page */
@media screen and (max-width: 949px) {
#logo-area {
padding-right: 0;
padding-top: 0;
position: fixed;
line-height: 0;
margin-top: -2rem;
width: 100%;
text-align: center;
}
#cobalt-main-box {
width: 80%;
display: flex;
border: none;
padding: 0;
}
.popup, .popup.scrollable {
border: none;
width: 90%;
height: 90%;
max-height: 100%;
}
.bottom-link {
padding-bottom: 2rem;
}
}
@media screen and (max-width: 524px) {
#logo-area {
padding-right: 0;
padding-top: 0;
position: fixed;
line-height: 0;
margin-top: -2rem;
width: 100%;
text-align: center;
}
#cobalt-main-box {
width: 90%;
display: flex;
border: none;
padding: 0;
}
.popup, .popup.scrollable {
border: none;
width: 90%;
height: 90%;
max-height: 100%;
}
.bottom-link {
padding-bottom: 2rem;
}
}

203
src/front/cobalt.js Normal file
View File

@@ -0,0 +1,203 @@
let isIOS = navigator.userAgent.toLowerCase().match("iphone os");
let switchers = {
"theme": ["auto", "light", "dark"],
"youtubeFormat": ["mp4", "webm", "audio"],
"quality": ["max", "hig", "mid", "low"]
}
function eid(id) {
return document.getElementById(id)
}
function enable(id) {
eid(id).dataset.enabled = "true";
}
function disable(id) {
eid(id).dataset.enabled = "false";
}
function vis(state) {
return (state === 1) ? "visible" : "hidden";
}
function changeDownloadButton(action, text) {
switch (action) {
case 0:
eid("download-button").disabled = true
if (localStorage.getItem("alwaysVisibleButton") == "true") {
eid("download-button").value = text
eid("download-button").style.padding = '0 1rem'
} else {
eid("download-button").value = ''
eid("download-button").style.padding = '0'
}
break;
case 1:
eid("download-button").disabled = false
eid("download-button").value = text
eid("download-button").style.padding = '0 1rem'
break;
case 2:
eid("download-button").disabled = true
eid("download-button").value = text
eid("download-button").style.padding = '0 1rem'
break;
}
}
document.addEventListener("keydown", function(event) {
if (event.key == "Tab") {
eid("download-button").value = '>>'
eid("download-button").style.padding = '0 1rem'
}
})
function button() {
let regex = /https:\/\/(www\.)?[-a-zA-Z0-9@:%._\+~#=]{1,256}\.[a-zA-Z0-9()]{1,6}\b([-a-zA-Z0-9()!@:%_\+.~#?&\/\/=]*)/.test(eid("url-input-area").value);
regex ? changeDownloadButton(1, '>>') : changeDownloadButton(0, '>>');
}
function copy(id, data) {
let e = document.getElementById(id);
e.classList.add("text-backdrop");
data ? navigator.clipboard.writeText(data) : navigator.clipboard.writeText(e.innerText);
setTimeout(() => { e.classList.remove("text-backdrop") }, 600);
}
function detectColorScheme() {
let theme = "auto";
let localTheme = localStorage.getItem("theme");
if (localTheme) {
theme = localTheme;
} else if (!window.matchMedia) {
theme = "dark"
}
document.documentElement.setAttribute("data-theme", theme);
}
function popup(type, action, text) {
eid("popup-backdrop").style.visibility = vis(action);
switch (type) {
case "about":
eid("popup-about").style.visibility = vis(action);
if (!localStorage.getItem("seenAbout")) localStorage.setItem("seenAbout", "true");
break;
case "error":
eid("desc-error").innerHTML = text;
eid("popup-error").style.visibility = vis(action);
break;
case "download":
if (action == 1) {
eid("pd-download").href = text;
eid("pd-copy").setAttribute("onClick", `copy('pd-copy', '${text}')` );
}
eid("popup-download").style.visibility = vis(action);
break;
default:
eid(`popup-${type}`).style.visibility = vis(action);
break;
}
}
function changeSwitcher(li, b, u) {
if (u) localStorage.setItem(li, b);
if (b) {
for (i in switchers[li]) {
(switchers[li][i] == b) ? enable(`${li}-${b}`) : disable(`${li}-${switchers[li][i]}`)
}
if (li == "theme") detectColorScheme();
} else {
localStorage.setItem(li, switchers[li][0]);
for (i in switchers[li]) {
(switchers[li][i] == switchers[li][0]) ? enable(`${li}-${switchers[li][0]}`) : disable(`${li}-${switchers[li][i]}`)
}
}
}
function internetError() {
eid("url-input-area").disabled = false
changeDownloadButton(2, '!!')
popup("error", 1, loc.noInternet);
}
function checkbox(action) {
if (eid(action).checked) {
localStorage.setItem(action, "true");
if (action == "alwaysVisibleButton") button();
} else {
localStorage.setItem(action, "false");
if (action == "alwaysVisibleButton") button();
}
}
function loadSettings() {
if (localStorage.getItem("alwaysVisibleButton") == "true") {
eid("alwaysVisibleButton").checked = true;
eid("download-button").value = '>>'
eid("download-button").style.padding = '0 1rem';
}
if (localStorage.getItem("downloadPopup") == "true" && !isIOS) {
eid("downloadPopup").checked = true;
}
changeSwitcher("theme", localStorage.getItem("theme"))
changeSwitcher("youtubeFormat", localStorage.getItem("youtubeFormat"))
changeSwitcher("quality", localStorage.getItem("quality"))
}
async function download(url) {
changeDownloadButton(2, '...');
eid("url-input-area").disabled = true;
let format = '';
if (url.includes("youtube.com/") || url.includes("/youtu.be/")) {
format = `&format=${localStorage.getItem("youtubeFormat")}`
}
fetch(`/api/json?quality=${localStorage.getItem("quality")}${format}&url=${encodeURIComponent(url)}`).then(async (response) => {
let j = await response.json();
if (j.status != "error" && j.status != "rate-limit") {
if (j.url) {
switch (j.status) {
case "redirect":
changeDownloadButton(2, '>>>')
setTimeout(() => {
changeDownloadButton(1, '>>')
eid("url-input-area").disabled = false
}, 3000)
if (localStorage.getItem("downloadPopup") == "true") {
popup('download', 1, j.url)
} else {
window.open(j.url, '_blank');
}
break;
case "stream":
changeDownloadButton(2, '?..')
fetch(`${j.url}&p=1&origin=front`).then(async (response) => {
let jp = await response.json();
if (jp.status == "continue") {
changeDownloadButton(2, '>>>')
window.location.href = j.url
setTimeout(() => {
changeDownloadButton(1, '>>')
eid("url-input-area").disabled = false
}, 5000)
} else {
eid("url-input-area").disabled = false
changeDownloadButton(2, '!!')
popup("error", 1, jp.text);
}
}).catch((error) => internetError());
break;
}
} else {
eid("url-input-area").disabled = false
changeDownloadButton(2, '!!')
popup("error", 1, loc.noURLReturned);
}
} else {
eid("url-input-area").disabled = false
changeDownloadButton(2, '!!')
popup("error", 1, j.text);
}
}).catch((error) => internetError());
}
window.onload = function () {
loadSettings();
detectColorScheme();
changeDownloadButton(0, '>>');
eid("cobalt-main-box").style.visibility = 'visible';
eid("footer").style.visibility = 'visible';
eid("url-input-area").value = "";
if (!localStorage.getItem("seenAbout")) popup('about', 1);
if (isIOS) localStorage.setItem("downloadPopup", "true");
}
eid("url-input-area").addEventListener("keyup", (event) => {
if (event.key === 'Enter') {
eid("download-button").click();
}
})

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

View File

@@ -0,0 +1 @@
@font-face{font-family:'Noto Sans Mono';font-style:normal;font-weight:500;font-stretch:100%;font-display:swap;src:url('files/notosansmono_DdVXQQ.woff2') format('woff2');unicode-range:U+0460-052F, U+1C80-1C88, U+20B4, U+2DE0-2DFF, U+A640-A69F, U+FE2E-FE2F}@font-face{font-family:'Noto Sans Mono';font-style:normal;font-weight:500;font-stretch:100%;font-display:swap;src:url('files/notosansmono_ndVXQQ.woff2') format('woff2');unicode-range:U+0400-045F, U+0490-0491, U+04B0-04B1, U+2116}@font-face{font-family:'Noto Sans Mono';font-style:normal;font-weight:500;font-stretch:100%;font-display:swap;src:url('files/notosansmono_HdVXQQ.woff2') format('woff2');unicode-range:U+1F00-1FFF}@font-face{font-family:'Noto Sans Mono';font-style:normal;font-weight:500;font-stretch:100%;font-display:swap;src:url('files/notosansmono_7dVXQQ.woff2') format('woff2');unicode-range:U+0370-03FF}@font-face{font-family:'Noto Sans Mono';font-style:normal;font-weight:500;font-stretch:100%;font-display:swap;src:url('files/notosansmono_LdVXQQ.woff2') format('woff2');unicode-range:U+0102-0103, U+0110-0111, U+0128-0129, U+0168-0169, U+01A0-01A1, U+01AF-01B0, U+1EA0-1EF9, U+20AB}@font-face{font-family:'Noto Sans Mono';font-style:normal;font-weight:500;font-stretch:100%;font-display:swap;src:url('files/notosansmono_PdVXQQ.woff2') format('woff2');unicode-range:U+0100-024F, U+0259, U+1E00-1EFF, U+2020, U+20A0-20AB, U+20AD-20CF, U+2113, U+2C60-2C7F, U+A720-A7FF}@font-face{font-family:'Noto Sans Mono';font-style:normal;font-weight:500;font-stretch:100%;font-display:swap;src:url('files/notosansmono_3dVQ.woff2') format('woff2');unicode-range:U+0000-00FF, U+0131, U+0152-0153, U+02BB-02BC, U+02C6, U+02DA, U+02DC, U+2000-206F, U+2074, U+20AC, U+2122, U+2191, U+2193, U+2212, U+2215, U+FEFF, U+FFFD}

Binary file not shown.

After

Width:  |  Height:  |  Size: 3.5 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 9.6 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 3.2 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 215 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 365 B

BIN
src/front/icons/favicon.ico Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 9.4 KiB

BIN
src/front/icons/generic.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 9.6 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.6 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 39 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 3.5 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 8.5 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 854 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 14 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.5 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.7 KiB

BIN
src/front/icons/wide.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 13 KiB

View File

@@ -0,0 +1 @@
{"name":"cobalt","short_name":"cobalt","start_url":"/","icons":[{"src":"/icons/android-chrome-192x192.png","sizes":"192x192","type":"image/png"},{"src":"/icons/android-chrome-512x512.png","sizes":"512x512","type":"image/png"},{"src":"/icons/generic.png","sizes":"512x512","type":"image/png","purpose":"any"},{"src":"/icons/maskable/x48.png","sizes":"48x48","type":"image/png","purpose":"maskable"},{"src":"/icons/maskable/x72.png","sizes":"72x72","type":"image/png","purpose":"maskable"},{"src":"/icons/maskable/x96.png","sizes":"96x96","type":"image/png","purpose":"maskable"},{"src":"/icons/maskable/x128.png","sizes":"128x128","type":"image/png","purpose":"maskable"},{"src":"/icons/maskable/x192.png","sizes":"192x192","type":"image/png","purpose":"maskable"},{"src":"/icons/maskable/x384.png","sizes":"384x384","type":"image/png","purpose":"maskable"},{"src":"/icons/maskable/x512.png","sizes":"512x512","type":"image/png","purpose":"maskable"},{"src":"/icons/maskable/x1280.png","sizes":"1280x1280","type":"image/png","purpose":"maskable"}],"theme_color":"#000000","background_color":"#000000","display":"standalone"}

2
src/front/robots.txt Normal file
View File

@@ -0,0 +1,2 @@
User-Agent: *
Disallow: /icons/ /fonts/ *.js *.css