remove bloat fonts, get rid of svelte-i18n
Signed-off-by: ngn <ngn@ngn.tf>
This commit is contained in:
58
app/src/components/card.svelte
Normal file
58
app/src/components/card.svelte
Normal file
@@ -0,0 +1,58 @@
|
||||
<script>
|
||||
export let title = "";
|
||||
export let id = "";
|
||||
</script>
|
||||
|
||||
<main {id}>
|
||||
{#if title === ""}
|
||||
<div><slot></slot></div>
|
||||
{:else}
|
||||
<h1>{title}</h1>
|
||||
<div class="padded"><slot></slot></div>
|
||||
{/if}
|
||||
</main>
|
||||
|
||||
<style>
|
||||
main {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
height: min-content;
|
||||
}
|
||||
|
||||
main h1 {
|
||||
font-family: var(--monospace);
|
||||
font-size: var(--size-6);
|
||||
|
||||
color: var(--white-1);
|
||||
background: var(--black-1);
|
||||
|
||||
position: relative;
|
||||
top: 20px;
|
||||
right: 7px;
|
||||
|
||||
width: min-content;
|
||||
padding-right: 10px;
|
||||
}
|
||||
|
||||
main h1::before {
|
||||
color: var(--white-3);
|
||||
content: "#";
|
||||
margin: 0 10px 0 0;
|
||||
}
|
||||
|
||||
main div {
|
||||
color: var(--white-2);
|
||||
|
||||
font-size: var(--size-3);
|
||||
line-height: 1.5em;
|
||||
word-wrap: break-word;
|
||||
|
||||
flex: 1;
|
||||
align-items: center;
|
||||
}
|
||||
|
||||
main .padded {
|
||||
padding: 25px 20px 18px 20px;
|
||||
border: solid 1px var(--black-3);
|
||||
}
|
||||
</style>
|
94
app/src/components/footer.svelte
Normal file
94
app/src/components/footer.svelte
Normal file
@@ -0,0 +1,94 @@
|
||||
<script>
|
||||
import { _ } from "$lib/locale.js";
|
||||
import { date, date_from_ts } from "$lib/util.js";
|
||||
import api from "$lib/api.js";
|
||||
|
||||
import { onMount } from "svelte";
|
||||
|
||||
let data = null;
|
||||
|
||||
onMount(async () => {
|
||||
data = await api.metrics(fetch);
|
||||
});
|
||||
</script>
|
||||
|
||||
<footer>
|
||||
<ul>
|
||||
<li>
|
||||
<a href={import.meta.env.WEBSITE_SOURCE_URL}>{$_("footer.source")}</a>
|
||||
</li>
|
||||
<li>
|
||||
<a href="/doc/license">{$_("footer.license")}</a>
|
||||
</li>
|
||||
<li>
|
||||
<a href="/doc/privacy">{$_("footer.privacy")}</a>
|
||||
</li>
|
||||
</ul>
|
||||
{#if data === null}
|
||||
<span>
|
||||
{$_("footer.render", {
|
||||
time: date(new Date()),
|
||||
})}
|
||||
</span>
|
||||
{:else}
|
||||
<span>
|
||||
{$_("footer.number", {
|
||||
total: data.total,
|
||||
since: date_from_ts(data.since),
|
||||
})}
|
||||
{#if data.total % 1000 === 0}
|
||||
<span class="wow">({$_("footer.wow")})</span>
|
||||
{/if}
|
||||
</span>
|
||||
{/if}
|
||||
</footer>
|
||||
|
||||
<style>
|
||||
footer {
|
||||
background: var(--glass);
|
||||
border-top: solid 2px var(--color);
|
||||
|
||||
display: flex;
|
||||
flex-direction: row;
|
||||
justify-content: space-between;
|
||||
align-items: center;
|
||||
|
||||
box-sizing: border-box;
|
||||
padding: 15px 40px;
|
||||
}
|
||||
|
||||
footer ul {
|
||||
list-style: none;
|
||||
|
||||
display: flex;
|
||||
flex-direction: row;
|
||||
gap: 5px;
|
||||
|
||||
font-size: var(--size-2);
|
||||
text-align: left;
|
||||
}
|
||||
|
||||
footer ul li a {
|
||||
text-decoration: none;
|
||||
font-weight: 200;
|
||||
}
|
||||
|
||||
footer ul li a:hover {
|
||||
color: var(--color);
|
||||
}
|
||||
|
||||
footer ul li:not(:last-of-type)::after {
|
||||
content: " / ";
|
||||
color: var(--white-3);
|
||||
font-weight: 900;
|
||||
}
|
||||
|
||||
footer span {
|
||||
color: var(--white-2);
|
||||
font-size: 15px;
|
||||
}
|
||||
|
||||
footer .wow {
|
||||
color: var(--color);
|
||||
}
|
||||
</style>
|
32
app/src/components/head.svelte
Normal file
32
app/src/components/head.svelte
Normal file
@@ -0,0 +1,32 @@
|
||||
<script>
|
||||
import { locale } from "$lib/locale.js";
|
||||
import api from "$lib/api.js";
|
||||
|
||||
export let desc, title;
|
||||
</script>
|
||||
|
||||
<svelte:head>
|
||||
<title>ngn.tf | {title}</title>
|
||||
|
||||
<!-- standart metadata tags -->
|
||||
|
||||
<meta name="description" content={desc} />
|
||||
<meta name="author" content="ngn" />
|
||||
<meta name="keywords" content="ngn,ngn13,ngn.tf" />
|
||||
<meta name="color-scheme" content="only dark" />
|
||||
<meta name="theme-color" content="#000000" />
|
||||
|
||||
<!-- open graph meta tags -->
|
||||
|
||||
<meta property="og:title" content="ngn.tf | {title}" />
|
||||
<meta property="og:description" content={desc} />
|
||||
|
||||
<!-- atom feed for the service updates -->
|
||||
|
||||
<link
|
||||
rel="alternate"
|
||||
type="application/atom+xml"
|
||||
href={api.join("/news/" + $locale.code)}
|
||||
title="Service news and updates"
|
||||
/>
|
||||
</svelte:head>
|
119
app/src/components/header.svelte
Normal file
119
app/src/components/header.svelte
Normal file
@@ -0,0 +1,119 @@
|
||||
<script>
|
||||
import { onMount } from "svelte";
|
||||
import { browser } from "$app/environment";
|
||||
|
||||
import { _ } from "$lib/locale.js";
|
||||
|
||||
export let picture = "";
|
||||
export let title = "";
|
||||
|
||||
let title_cur = title;
|
||||
let javascript = false;
|
||||
|
||||
// TODO: make the animation first delete and then type
|
||||
|
||||
// do the typing animation
|
||||
function animate(title) {
|
||||
// animation is displayed in the browser obv
|
||||
if (!browser) {
|
||||
return;
|
||||
}
|
||||
|
||||
// clear any previous timeouts
|
||||
let id = window.setTimeout(function () {}, 0);
|
||||
while (id--) {
|
||||
clearTimeout(id);
|
||||
}
|
||||
|
||||
// reset the current title and add each letter with a timeout to give the
|
||||
// epic typing effect
|
||||
title_cur = "";
|
||||
|
||||
for (let i = 0; i < title.length; i++) {
|
||||
setTimeout(() => {
|
||||
title_cur += title[i];
|
||||
}, i * 70);
|
||||
}
|
||||
}
|
||||
|
||||
onMount(() => {
|
||||
javascript = true;
|
||||
});
|
||||
|
||||
$: animate(title);
|
||||
</script>
|
||||
|
||||
<header>
|
||||
<div>
|
||||
{#if javascript}
|
||||
<h1 class="title">{title_cur}</h1>
|
||||
<h1 class="cursor">_</h1>
|
||||
{:else}
|
||||
<h1 class="title">{title}</h1>
|
||||
{/if}
|
||||
</div>
|
||||
<img src="/assets/{picture}.png" alt="" />
|
||||
</header>
|
||||
|
||||
<style>
|
||||
header {
|
||||
background: var(--transparent);
|
||||
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
display: flex;
|
||||
flex-direction: row;
|
||||
justify-content: space-between;
|
||||
align-items: end;
|
||||
}
|
||||
|
||||
header div {
|
||||
display: flex;
|
||||
flex-direction: row;
|
||||
align-items: end;
|
||||
padding: 40px 40px 10px 40px;
|
||||
font-size: var(--size-6);
|
||||
font-family:
|
||||
Consolas,
|
||||
Monaco,
|
||||
Lucida Console,
|
||||
Liberation Mono,
|
||||
DejaVu Sans Mono,
|
||||
Bitstream Vera Sans Mono,
|
||||
Courier New,
|
||||
monospace;
|
||||
white-space: nowrap;
|
||||
justify-content: start;
|
||||
width: min-content;
|
||||
}
|
||||
|
||||
header h1 {
|
||||
color: var(--color);
|
||||
}
|
||||
|
||||
header div .title {
|
||||
text-shadow: var(--text-shadow);
|
||||
overflow: hidden;
|
||||
}
|
||||
|
||||
header div .cursor {
|
||||
content: "_";
|
||||
display: inline-block;
|
||||
animation: blink 1.5s steps(2) infinite;
|
||||
}
|
||||
|
||||
header img {
|
||||
width: 220px;
|
||||
padding: 50px 50px 0 50px;
|
||||
}
|
||||
|
||||
@media only screen and (max-width: 900px) {
|
||||
header {
|
||||
display: block;
|
||||
}
|
||||
|
||||
header img {
|
||||
display: none;
|
||||
}
|
||||
}
|
||||
</style>
|
34
app/src/components/language.svelte
Normal file
34
app/src/components/language.svelte
Normal file
@@ -0,0 +1,34 @@
|
||||
<script>
|
||||
import { localizer, next } from "$lib/locale.js";
|
||||
import { onMount } from "svelte";
|
||||
|
||||
// "show" is simply used to not display the locale button when javascript is
|
||||
// not enabled, bc it does not function without javascript
|
||||
let show = false;
|
||||
|
||||
onMount(() => {
|
||||
show = true;
|
||||
});
|
||||
</script>
|
||||
|
||||
{#if show}
|
||||
<!-- TODO: make this work without javascript -->
|
||||
<button on:click={() => localizer.switch()}>
|
||||
{$next.icon}
|
||||
</button>
|
||||
{/if}
|
||||
|
||||
<style>
|
||||
button {
|
||||
background: none;
|
||||
color: var(--white-1);
|
||||
font-size: var(--size-4);
|
||||
outline: none;
|
||||
border: none;
|
||||
transition: 0.4s;
|
||||
}
|
||||
|
||||
button:hover {
|
||||
background: var(--black-1);
|
||||
}
|
||||
</style>
|
46
app/src/components/navbar.svelte
Normal file
46
app/src/components/navbar.svelte
Normal file
@@ -0,0 +1,46 @@
|
||||
<script>
|
||||
import Page from "$components/page.svelte";
|
||||
import Language from "$components/language.svelte";
|
||||
|
||||
import { _ } from "$lib/locale.js";
|
||||
</script>
|
||||
|
||||
<nav>
|
||||
<h3>ngn.tf</h3>
|
||||
<div>
|
||||
<Page link="/">{$_("navbar.home")}</Page>
|
||||
<Page link="/services">{$_("navbar.services")}</Page>
|
||||
<Page link="/donate">{$_("navbar.donate")}</Page>
|
||||
<Language />
|
||||
</div>
|
||||
</nav>
|
||||
|
||||
<style>
|
||||
nav {
|
||||
display: flex;
|
||||
flex-direction: row;
|
||||
align-items: center;
|
||||
justify-content: space-between;
|
||||
|
||||
background: var(--glass);
|
||||
box-shadow: var(--box-shadow);
|
||||
border-bottom: solid 2px var(--color);
|
||||
|
||||
padding: 15px 40px;
|
||||
}
|
||||
|
||||
nav div {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
flex-wrap: wrap;
|
||||
justify-content: right;
|
||||
gap: 15px;
|
||||
}
|
||||
|
||||
nav h3 {
|
||||
color: var(--color);
|
||||
font-family: var(--monospace);
|
||||
font-size: var(--size-4);
|
||||
font-weight: 900;
|
||||
}
|
||||
</style>
|
35
app/src/components/page.svelte
Normal file
35
app/src/components/page.svelte
Normal file
@@ -0,0 +1,35 @@
|
||||
<script>
|
||||
import { click } from "$lib/util.js";
|
||||
import { page } from "$app/stores";
|
||||
|
||||
export let link;
|
||||
</script>
|
||||
|
||||
<a
|
||||
class={$page.url.pathname === link ? "active" : "inactive"}
|
||||
data-sveltekit-preload-data
|
||||
on:click={click}
|
||||
href={link}
|
||||
>
|
||||
<slot></slot>
|
||||
</a>
|
||||
|
||||
<style>
|
||||
a {
|
||||
font-weight: 600;
|
||||
font-size: var(--size-3);
|
||||
|
||||
color: var(--white-1);
|
||||
text-decoration: none;
|
||||
text-decoration-color: var(--color);
|
||||
}
|
||||
|
||||
a:hover {
|
||||
color: var(--color);
|
||||
text-decoration: underline;
|
||||
}
|
||||
|
||||
.active {
|
||||
color: var(--color);
|
||||
}
|
||||
</style>
|
138
app/src/components/service.svelte
Normal file
138
app/src/components/service.svelte
Normal file
@@ -0,0 +1,138 @@
|
||||
<script>
|
||||
import { time_from_ts } from "$lib/util.js";
|
||||
import { _, locale } from "$lib/locale.js";
|
||||
|
||||
export let service = {};
|
||||
</script>
|
||||
|
||||
<main>
|
||||
<div class="info">
|
||||
<div>
|
||||
<h1>{service.name}</h1>
|
||||
<p>{service.desc[$locale.code]}</p>
|
||||
</div>
|
||||
<ul>
|
||||
<li><a href={service.clear}> Clear</a></li>
|
||||
<li><a href={service.onion}>TOR</a></li>
|
||||
<li><a href={service.i2p}> I2P</a></li>
|
||||
</ul>
|
||||
</div>
|
||||
<div class="check">
|
||||
<h1>
|
||||
{$_("services.last", {
|
||||
time: time_from_ts(service.check_time),
|
||||
})}
|
||||
</h1>
|
||||
{#if service.check_res == 0}
|
||||
<span style="background: var(--white-2)">
|
||||
{$_("services.status.down")}
|
||||
</span>
|
||||
{:else if service.check_res == 1}
|
||||
<span style="background: var(--color)">
|
||||
{$_("services.status.up")}
|
||||
</span>
|
||||
{:else if service.check_res == 2}
|
||||
<span style="background: var(--color); filter: brightness(50%);">
|
||||
{$_("services.status.slow")}
|
||||
</span>
|
||||
{/if}
|
||||
</div>
|
||||
</main>
|
||||
|
||||
<style>
|
||||
main {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
|
||||
background: var(--black-2);
|
||||
border: solid 1px var(--black-3);
|
||||
text-align: left;
|
||||
|
||||
flex-grow: 1;
|
||||
}
|
||||
|
||||
main .info {
|
||||
display: flex;
|
||||
flex-direction: row;
|
||||
align-items: start;
|
||||
justify-content: space-between;
|
||||
flex: 1;
|
||||
|
||||
color: var(--white-1);
|
||||
padding: 15px 18px;
|
||||
}
|
||||
|
||||
main .info div h1 {
|
||||
font-size: var(--size-4);
|
||||
font-weight: 900;
|
||||
}
|
||||
|
||||
main .info div p {
|
||||
font-size: var(--size-2);
|
||||
color: var(--white-2);
|
||||
font-weight: 100;
|
||||
}
|
||||
|
||||
main .info ul {
|
||||
display: flex;
|
||||
flex-direction: row;
|
||||
gap: 5px;
|
||||
|
||||
text-align: right;
|
||||
list-style: none;
|
||||
}
|
||||
|
||||
main .info ul li:not(:last-of-type)::after {
|
||||
content: " / ";
|
||||
color: var(--white-3);
|
||||
font-weight: 900;
|
||||
}
|
||||
|
||||
main .info li a {
|
||||
color: var(--color);
|
||||
text-decoration: none;
|
||||
|
||||
font-size: var(--size-2);
|
||||
font-weight: 100;
|
||||
}
|
||||
|
||||
main .info li a:hover {
|
||||
text-decoration: underline;
|
||||
}
|
||||
|
||||
main .info li a[href=""] {
|
||||
color: var(--white-3);
|
||||
cursor: not-allowed;
|
||||
}
|
||||
|
||||
main .info li a[href=""]:hover {
|
||||
text-decoration: none;
|
||||
text-shadow: none;
|
||||
}
|
||||
|
||||
main .check {
|
||||
border-top: solid 1px var(--black-3);
|
||||
display: flex;
|
||||
flex-direction: row;
|
||||
align-items: center;
|
||||
justify-content: space-between;
|
||||
color: var(--white-1);
|
||||
}
|
||||
|
||||
main .check h1 {
|
||||
font-size: var(--size-2);
|
||||
font-weight: 100;
|
||||
|
||||
color: var(--white-2);
|
||||
padding: 5px 18px;
|
||||
}
|
||||
|
||||
main .check span {
|
||||
font-size: var(--size-4);
|
||||
font-weight: 1000;
|
||||
|
||||
color: var(--black-1);
|
||||
padding: 5px 18px;
|
||||
text-transform: uppercase;
|
||||
}
|
||||
</style>
|
Reference in New Issue
Block a user