Rename FNX to Nova

This commit is contained in:
2026-01-26 22:23:36 +01:00
parent 70e8353a50
commit 70a22d4a06
22 changed files with 67 additions and 43 deletions

View File

@@ -97,7 +97,7 @@ export class FSNavigator {
// we still replace the URL with replaceState. This way the user is not
// greeted to a 404 page when refreshing after renaming a file
if (this.history_enabled) {
window.document.title = node.path[node.base_index].name + " / FNX"
window.document.title = node.path[node.base_index].name + " / Nova"
const url = "/d" + fs_encode_path(node.path[node.base_index].path) + window.location.hash
if (push_history) {
window.history.pushState({}, window.document.title, url)

View File

@@ -387,16 +387,8 @@ run(() => {
{#if creating_dir}
<CreateDirectory nav={nav} />
{/if}
{#if $nav.base.path === "/me"}
<div class="highlight_shaded" style="background-color: rgba(255, 255, 0, 0.05); border-radius: 0;">
The filesystem is experimental!
<a href="/filesystem">Please read the guide</a>
</div>
{/if}
</div>
{#if $nav.base.abuse_type !== undefined}
<div class="highlight_red">
This directory has received an abuse report. It cannot be

View File

@@ -22,7 +22,7 @@ let upload_widget
<div class="page_content">
<section>
<p>
FNX.storage is a platform for cost-effective cloud storage and
Nova.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>
@@ -36,7 +36,7 @@ let upload_widget
<div>€ 1 / TB</div>
</div>
</div>
<h2>What FNX is good at</h2>
<h2>What Nova is good at</h2>
<ul>
<li>
Serving large files to millions of people worldwide
@@ -147,11 +147,11 @@ header > h1 {
.header_image_container {
text-align: initial;
margin: auto;
margin-bottom: 1.5em; /*Offset for menu button*/
height: 150px;
margin-bottom: 50px;
height: 100px;
width: 500px;
max-width: 100%;
background-image: url("/res/img/header_orbitron.webp");
background-image: url("/res/img/header.webp");
background-repeat: no-repeat;
background-size: contain;
background-position: center;

View File

@@ -18,7 +18,7 @@ let egress = $state(10) // TB
let avg_file_size = $state(1000) // kB
$effect(() => {
// FNX has a minimum file size of 10kB. Calculate the number of files from
// Nova 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
@@ -67,14 +67,14 @@ $effect(() => {
<div class="bars">
<div>
<div>
FNX.storage - <Euro amount={fnx_total*1e6}/> / month<br/>
Nova.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
Nova counts a minimum file size of 10 kB. Files smaller than that
are rounded up to 10 kB.
</div>
{/if}
@@ -105,16 +105,16 @@ $effect(() => {
</div>
<p>
Note that while FNX.storage might not seem to be the cheapest option in some
Note that while Nova.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. FNX.storage includes no hidden costs, I only
pricing of these platforms. Nova.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.
them. Just assume that Nova wil be cheaper.
</p>
<style>

View File

@@ -88,7 +88,8 @@ const login = async (e?: SubmitEvent) => {
{
method: "POST",
body: fd,
credentials: "omit", // Dont send existing session cookies
// Allow server to set cookies
credentials: "include",
},
))
@@ -99,9 +100,6 @@ const login = async (e?: SubmitEvent) => {
}
}
// Save the session cookie
document.cookie = "pd_auth_key="+resp.auth_key+"; Max-Age=31536000;"
dispatch("login", {key: resp.auth_key})
if (typeof login_redirect === "string" && login_redirect.startsWith("/")) {

View File

@@ -2,6 +2,7 @@
import { preventDefault } from 'svelte/legacy';
import { loading_finish, loading_start } from "lib/Loading";
import { formatDate } from "util/Formatting";
import CopyButton from 'layout/CopyButton.svelte';
let loaded = $state(false)
let rows = $state([])
@@ -130,12 +131,15 @@ const logout = async (key) => {
<tbody>
{#each rows as row (row.auth_key)}
<tr style="border-bottom: none;">
<td>{row.auth_key}</td>
<td>
<CopyButton text={row.auth_key} small_icon>Copy</CopyButton>
{row.auth_key}
</td>
<td>{formatDate(row.creation_time, true, true, false)}</td>
<td>{formatDate(row.last_used_time, true, true, false)}</td>
<td>{row.creation_ip_address}</td>
<td>
<button onclick={preventDefault(() => {logout(row.auth_key)})} class="button button_red round">
<button onclick={(e) => {e.preventDefault();logout(row.auth_key)}} class="button button_red round">
<i class="icon">delete</i>
</button>
</td>

View File

@@ -3,6 +3,7 @@ import { get_endpoint, get_user, type User } from "lib/PixeldrainAPI";
import { onMount } from "svelte";
import HotlinkProgressBar from "user_home/HotlinkProgressBar.svelte";
import StorageProgressBar from "user_home/StorageProgressBar.svelte";
import { formatThousands } from "util/Formatting";
let transfer_cap = $state(0)
let transfer_used = $state(0)
@@ -53,6 +54,9 @@ onMount(async () => {
<StorageProgressBar used={user.storage_space_used} total={storage_limit}/>
<br/>
File count: {formatThousands(user.filesystem_node_count)}
<br/><br/>
Egress used (30 days):
(<a href="/user/sharing/bandwidth">set custom limit</a>)
<HotlinkProgressBar used={transfer_used} total={transfer_cap}></HotlinkProgressBar>

View File

@@ -1,6 +1,6 @@
<script lang="ts">
import { onMount } from "svelte";
import { formatDataVolume, formatNumber } from "./Formatting";
import { formatDataVolume, formatDuration, formatNumber } from "./Formatting";
import { color_by_name } from "./Util";
import {
Chart,
@@ -33,12 +33,14 @@ let {
legend = true,
tooltips = true,
ticks = true,
animations = true,
height = "300px"
}: {
data_type?: string;
legend?: boolean;
tooltips?: boolean;
ticks?: boolean;
animations?: boolean;
height?: string;
} = $props();
@@ -85,6 +87,9 @@ onMount(() => {
},
tooltip: {
enabled: tooltips,
itemSort: (a, b): number => {
return <number>b.raw - <number>a.raw
},
},
},
layout: {
@@ -102,6 +107,8 @@ onMount(() => {
callback: function (value: number, index: number, values: Tick[]) {
if (data_type == "bytes") {
return formatDataVolume(value, 3);
} else if (data_type === "duration") {
return formatDuration(value, 2);
}
return formatNumber(value, 3);
},
@@ -129,6 +136,11 @@ onMount(() => {
}
}
);
if (!animations) {
chart_object.options.animation = false
chart_object.options.transitions.active.animation.duration = 0
}
})
</script>

View File

@@ -58,11 +58,24 @@ const hour = minute * 60
const day = hour * 24
export const formatDuration = (ms: number, decimals: number) => {
let remainingDecimals = decimals
let res = ""
if (ms >= day) { res += Math.floor(ms / day) + "d " }
if (ms >= hour) { res += Math.floor((ms % day) / hour) + "h " }
if (ms >= minute) { res += Math.floor((ms % hour) / minute) + "m " }
return res + ((ms % minute) / second).toFixed(decimals) + "s"
if (ms >= day && remainingDecimals > 0) {
res += Math.floor(ms / day) + "d "
remainingDecimals--
}
if (ms >= hour && remainingDecimals > 0) {
res += Math.floor((ms % day) / hour) + "h "
remainingDecimals--
}
if (ms >= minute && remainingDecimals > 0) {
res += Math.floor((ms % hour) / minute) + "m "
remainingDecimals--
}
if (remainingDecimals > 0) {
res += ((ms % minute) / second).toFixed(remainingDecimals) + "s"
}
return res
}
export const formatDate = (

View File

@@ -49,7 +49,7 @@ const get_page = () => {
}
title = current_subpage === null ? current_page.title : current_subpage.title
window.document.title = title+" / FNX"
window.document.title = title+" / Nova"
}
let current_page: Tab = $state(null)

View File

@@ -98,7 +98,7 @@ const load_page = (pathname: string, history: boolean): boolean => {
return load_page("/login", true)
}
window.document.title = current_page.title+" / FNX"
window.document.title = current_page.title+" / Nova"
if(history) {
window.history.pushState({}, window.document.title, pathname)