Fix stats reporting. Add Vite compatibility

This commit is contained in:
2025-11-04 16:16:50 +01:00
parent aa29de9029
commit e54dc2dbd7
21 changed files with 1060 additions and 361 deletions

View File

@@ -32,10 +32,3 @@ import Euro from "util/Euro.svelte";
{:else}
<LoginRegister/>
{/if}
<style>
.page_content {
margin-top: 16px;
margin-bottom: 16px;
}
</style>

View File

@@ -22,45 +22,10 @@ let upload_widget
<div class="page_content">
<section>
<p>
Pixeldrain offers services for efficiently moving and storing
digital files on the internet.
FNX.storage is a platform for cost-effective cloud storage and
content delivery. We will store and serve your files at an extremely
competitive rate.
</p>
<h2>What pixeldrain is good at</h2>
<ul>
<li>
Serving large files to millions of people worldwide
</li>
<li>
Storing files for less money than all the competition
</li>
</ul>
<h2>Things we take very seriously</h2>
<ul>
<li>
<b>Performance</b> - Slow software is a waste of time. We
don't want to make you wait, so pixeldrain is completely
tuned for maximum performance
</li>
<li>
<b>Privacy</b> - There is too much tracking on the web
nowadays. Pixeldrain goes in the other direction, this site
does not contain any advertisements or third party tracking
scripts
</li>
<li>
Bullet lists
</li>
</ul>
<Pricing/>
</section>
</div>
<header>
<h1>Pricing</h1>
<span>(Prepaid plan. For monthly subscriptions, look further below)</span>
</header>
<div class="page_content">
<section>
<div class="prices">
<div>
<div>Storage pricing</div>
@@ -70,16 +35,25 @@ let upload_widget
<div>Egress pricing</div>
<div>€ 1 / TB</div>
</div>
<div>
<div>Minimum fee *</div>
<div>€1 / month</div>
</div>
</div>
<p style="text-align: center;">
* The minimum fee is only charged when usage is less than €1
</p>
<h2>What FNX is good at</h2>
<ul>
<li>
Serving large files to millions of people worldwide
</li>
<li>
Storing files for less money than all the competition
</li>
</ul>
<Pricing/>
</section>
</div>
<h2>What you get</h2>
<header>
<h1>Features</h1>
</header>
<div class="page_content">
<section>
<ul>
<li>
<span class="bold">Unlimited</span> storage space
@@ -136,17 +110,16 @@ let upload_widget
</header>
<GetStarted/>
<header id="pro">
<h1>Subscription plans</h1>
</header>
<div class="page_content">
<FeatureTable/>
</div>
<br/>
<br/>
<br/>
<br/>
<br/>
<svelte:head>
<style>
body {
background-image: url("/res/img/catspaw.webp");
background-image: url("/res/img/northernlights.webp");
background-repeat: no-repeat;
background-attachment: fixed;
background-position: center;
@@ -164,10 +137,9 @@ header {
padding-top: 0;
padding-bottom: 0;
}
header > h1,
header > span {
header > h1 {
color: #ffffff;
text-shadow: 0 0 4px #000000;
text-shadow: 0 0 6px #000000;
margin-top: 30px;
margin-bottom: 30px;
}
@@ -209,17 +181,23 @@ header > span {
flex: 1 0 200px;
min-width: 200px;
display: flex;
flex-direction: column;
flex-direction: row;
text-align: center;
border-radius: 6px;
overflow: hidden;
border: 2px solid var(--card_color);
}
.prices > div > div {
flex: 1 1 auto;
padding: 4px;
font-size: 1.3em;
}
.prices > div > div:nth-child(2) {
background: var(--card_color);
font-size: 1.3em;
}
@media(max-width: 1000px) {
.prices > div {
flex-direction: column;
}
}
</style>

View File

@@ -1,31 +1,28 @@
<script>
import { run } from 'svelte/legacy';
import { onMount } from "svelte";
import Euro from "util/Euro.svelte";
import ProgressBar from "util/ProgressBar.svelte";
let pixeldrain_storage = $state(0)
let pixeldrain_egress = $state(0)
let pixeldrain_total = $state(0)
let fnx_storage = $state(0)
let fnx_egress = $state(0)
let fnx_total = $state(0)
let backblaze_storage = $state(0)
let backblaze_egress = $state(0)
let backblaze_api = $state(0)
let backblaze_total = $state(0)
let wasabi_storage = $state(0)
let wasabi_total = $state(0)
let price_amazon = 0
let price_azure = 0
let price_google = 0
let price_max = $state(0)
let storage = $state(10) // TB
let egress = $state(10) // TB
let avg_file_size = $state(1000) // kB
run(() => {
pixeldrain_storage = storage * 4
pixeldrain_egress = egress * 1
pixeldrain_total = pixeldrain_storage + pixeldrain_egress
$effect(() => {
// FNX has a minimum file size of 10kB. Calculate the number of files from
// storage and avg file size, then calculate storage usage based on that.
fnx_storage = Math.max(storage * 4, ((storage*10)/avg_file_size)*4)
fnx_egress = egress * 1
fnx_total = fnx_storage + fnx_egress
// Egress at Backblaze is free up to three times the amount of storage, then
// it's $10/TB
@@ -34,45 +31,53 @@ run(() => {
backblaze_api = ((egress * 1e12) / (avg_file_size * 1e3)) * 0.0000004
backblaze_total = backblaze_storage + backblaze_egress + backblaze_api
// Wasabi does not have egress fees
wasabi_storage = storage * 6.99
wasabi_total = (egress > storage) ? 0 : wasabi_storage
// price_amazon = (storage * 26) + (egress * 90)
// price_azure = (storage * 20) + (egress * 80)
// price_google = (storage * 20) + (egress * 20)
price_max = Math.max(pixeldrain_total, backblaze_total, wasabi_total, price_amazon, price_azure, price_google)
price_max = Math.max(fnx_total, backblaze_total, wasabi_total)
});
onMount(() => {})
</script>
<h2>Price calculator</h2>
<div class="inputs">
<div>
<div>Storage</div>
<div><input type="number" bind:value={storage}> TB / month</div>
<div class="usage_label">Storage</div>
<div class="usage_input">
<input type="number" bind:value={storage}/>
<div>TB / month</div>
</div>
</div>
<div>
<div>Egress</div>
<div><input type="number" bind:value={egress}> TB / month</div>
<div class="usage_label">Egress</div>
<div class="usage_input">
<input type="number" bind:value={egress}/>
<div>TB / month</div>
</div>
</div>
<div>
<div>Average file size</div>
<div><input type="number" bind:value={avg_file_size}> kB</div>
<div class="usage_label">Average file size</div>
<div class="usage_input">
<input type="number" bind:value={avg_file_size}/>
<div>kB</div>
</div>
</div>
</div>
<div class="bars">
<div>
<div>
Pixeldrain - <Euro amount={pixeldrain_total*1e6}/> / month<br/>
<Euro amount={pixeldrain_storage*1e6}/> storage,
<Euro amount={pixeldrain_egress*1e6}/> egress
<ProgressBar used={pixeldrain_total} total={price_max}/>
FNX.storage - <Euro amount={fnx_total*1e6}/> / month<br/>
<Euro amount={fnx_storage*1e6}/> storage,
<Euro amount={fnx_egress*1e6}/> egress
<ProgressBar used={fnx_total} total={price_max}/>
</div>
{#if avg_file_size < 10}
<div>
FNX counts a minimum file size of 10 kB. Files smaller than that
are rounded up to 10 kB.
</div>
{/if}
</div>
<div>
<div>
@@ -97,42 +102,20 @@ onMount(() => {})
</div>
{/if}
</div>
<!-- <div>
<div>
Amazon S3: <Euro symbol="$" amount={price_amazon*1e6}/> / month
<ProgressBar used={price_amazon} total={price_max}/>
</div>
<div>
Amazon's pricing is too complicated to accurately represent here.
</div>
</div>
<div>
<div>
Microsoft Azure: <Euro symbol="$" amount={price_azure*1e6}/> / month
<ProgressBar used={price_azure} total={price_max}/>
</div>
<div>
Azure's pricing is too complicated to accurately represent here.
</div>
</div>
<div>
<div>
Google: <Euro symbol="$" amount={price_google*1e6}/> / month
<ProgressBar used={price_google} total={price_max}/>
</div>
<div>
Google's pricing is too complicated to accurately represent here.
</div>
</div> -->
</div>
<p>
Note that while pixeldrain might not seem to be the cheapest option in some
Note that while FNX.storage might not seem to be the cheapest option in some
cases, most cloud providers have extra hidden costs for API calls and
region-specific prices. This makes it very hard to accurately compare the
pricing of these platforms. Pixeldrain includes no hidden costs, I only
pricing of these platforms. FNX.storage includes no hidden costs, I only
charge for storage and egress.
</p>
<p>
Large cloud providers like Amazon, Microsoft and Google are excluded from
this calculation because their pricing is too complex accurately compare
them. Just assume that FNX wil be cheaper.
</p>
<style>
.inputs {
@@ -142,14 +125,40 @@ onMount(() => {})
gap: 10px;
margin-bottom: 10px;
}
@media(max-width: 700px) {
.inputs {
flex-direction: column;
}
}
.inputs > div {
flex: 1 1 auto;
flex: 1 1 100%;
display: flex;
flex-direction: column;
border-radius: 6px;
overflow: hidden;
border: 2px solid var(--card_color);
}
.usage_label {
flex: 1 1 auto;
text-align: center;
font-size: 1.3em;
padding: 4px;
}
.usage_input {
flex: 1 1 auto;
background: var(--card_color);
display: flex;
flex-direction: row;
align-items: center;
}
.usage_input > input {
flex: 1 1 auto;
background: var(--card_color);
}
.usage_input > div {
flex: 0 0 auto;
background: var(--card_color);
}
.bars {
display: flex;
flex-direction: column;