Fully rename Pixeldrain to Nova

This commit is contained in:
2026-06-10 23:53:03 +02:00
parent 3c13cd1a14
commit 7b24a9d8cf
95 changed files with 321 additions and 1989 deletions

View File

@@ -1,11 +1,11 @@
{
"name": "pixeldrain-web",
"name": "nova-web",
"version": "1.0.0",
"lockfileVersion": 3,
"requires": true,
"packages": {
"": {
"name": "pixeldrain-web",
"name": "nova-web",
"version": "1.0.0",
"dependencies": {
"@sveltejs/vite-plugin-svelte": "^6.2.1",

View File

@@ -1,5 +1,5 @@
{
"name": "pixeldrain-web",
"name": "nova-web",
"version": "1.0.0",
"type": "module",
"scripts": {

View File

@@ -49,10 +49,10 @@ let block_form = {
let message = "The following files were blocked:<br/>"
message += "<ul>"
jresp.files_blocked.forEach(file => {
message += "<li>pixeldrain.com/u/" + file + "</li>"
message += "<li>nova.storage/u/" + file + "</li>"
})
jresp.filesystem_nodes_blocked.forEach(file => {
message += "<li>pixeldrain.com/d/" + file + "</li>"
message += "<li>nova.storage/d/" + file + "</li>"
})
message += "</ul>"
@@ -73,7 +73,7 @@ onMount(() => {
<section>
<h2>File removal</h2>
<p>
Paste any pixeldrain file links in here to remove them
Paste any Nova file links in here to remove them
</p>
<div class="highlight_border">
<Form config={block_form}></Form>

View File

@@ -1,7 +1,7 @@
<script lang="ts">
import { onMount, tick } from "svelte";
import EmailReportersTable from "./EmailReportersTable.svelte";
import { get_endpoint } from "lib/PixeldrainAPI";
import { get_endpoint } from "lib/NovaAPI";
import { loading_finish, loading_start } from "lib/Loading";
type Reporter = {

View File

@@ -5,7 +5,7 @@ import Chart from "util/Chart.svelte";
import { color_by_name } from "util/Util";
import ServerDiagnostics from "./ServerDiagnostics.svelte";
import PeerTable from "./PeerTable.svelte";
import { get_endpoint } from "lib/PixeldrainAPI";
import { get_endpoint } from "lib/NovaAPI";
let graphEgress: Chart = $state()
let graphDownloads: Chart = $state()

View File

@@ -1,5 +1,5 @@
import { loading_finish, loading_start } from "lib/Loading";
import { check_response, get_endpoint } from "lib/PixeldrainAPI";
import { check_response, get_endpoint } from "lib/NovaAPI";
import hsl2rgb from "pure-color/convert/hsl2rgb";
import rgb2hex from "pure-color/convert/rgb2hex";

View File

@@ -1,5 +1,5 @@
<script lang="ts">
import { get_endpoint } from "lib/PixeldrainAPI";
import { get_endpoint } from "lib/NovaAPI";
import { onMount } from "svelte";
import { formatDuration } from "util/Formatting";

View File

@@ -3,7 +3,7 @@ import { onMount } from "svelte";
import { formatDataVolume, formatDate } from "util/Formatting";
import SortButton from "layout/SortButton.svelte";
import { loading_finish, loading_start } from "lib/Loading";
import { get_endpoint } from "lib/PixeldrainAPI";
import { get_endpoint } from "lib/NovaAPI";
interface Props {
user_id?: string;

View File

@@ -1,6 +1,6 @@
<script lang="ts">
import { loading_finish, loading_start } from "lib/Loading";
import { get_endpoint } from "lib/PixeldrainAPI";
import { get_endpoint } from "lib/NovaAPI";
import { onMount } from "svelte";
import { formatDate } from "util/Formatting";

View File

@@ -1,5 +1,5 @@
<script lang="ts">
import PixeldrainLogo from "util/PixeldrainLogo.svelte";
import NovaLogo from "util/NovaLogo.svelte";
import Button from "layout/Button.svelte";
import Euro from "util/Euro.svelte";
import { formatDataVolume } from "util/Formatting";
@@ -10,7 +10,7 @@ let button: HTMLButtonElement = $state()
let dialog: Dialog = $state()
let {
no_login_label = "Pixeldrain",
no_login_label = "Nova",
hide_name = true,
hide_logo = false,
style = "",
@@ -32,7 +32,7 @@ const open = () => dialog.open(button.getBoundingClientRect())
<div class="wrapper">
<button bind:this={button} onclick={open} class="button round" title="Menu" style={style}>
{#if !hide_logo}
<PixeldrainLogo style="height: 1.6em; width: 1.6em;"/>
<NovaLogo style="height: 1.6em; width: 1.6em;"/>
{/if}
<span class="button_username" class:hide_name>
{$user.username === "" ? no_login_label : $user.username}

View File

@@ -1,6 +1,6 @@
<script lang="ts">
import Button from "layout/Button.svelte";
import { fs_delete_all, type FSNode } from "lib/FilesystemAPI.svelte";
import { fs_trash, type FSNode } from "lib/FilesystemAPI.svelte";
import type { FSNavigator } from "filesystem/FSNavigator";
import { loading_finish, loading_start } from "lib/Loading";
@@ -25,7 +25,7 @@ const delete_file = async (e: MouseEvent) => {
try {
loading_start()
await fs_delete_all(file.path)
await fs_trash(file.path)
} catch (err) {
console.error(err)
alert(err)
@@ -61,10 +61,10 @@ const delete_file = async (e: MouseEvent) => {
<fieldset>
<legend>Delete</legend>
<p>
Delete this file or directory. If this is a directory then all
subfiles will be deleted as well. This action cannot be undone.
Move this file or directory to the trash. You can restore it or
permanently delete it from the <a href="/d/me/.Trash">trash bin</a>.
</p>
<Button click={delete_file} red icon="delete" label="Delete" style="align-self: flex-start;"/>
<Button click={delete_file} red icon="delete" label="Move to trash" style="align-self: flex-start;"/>
</fieldset>
{/if}

View File

@@ -73,7 +73,7 @@ run(() => {
<fieldset>
<legend>Embedding</legend>
<p>
If you have a website you can embed pixeldrain directories and files in your
If you have a website you can embed Nova directories and files in your
own webpages with the code below. If you embed a directory then all
subdirectories and files will be accessible through the frame. Branding
options will also apply in the frame, but only when applied to this

View File

@@ -1,5 +1,5 @@
<script lang="ts">
import { fs_delete_all, fs_rename } from "lib/FilesystemAPI.svelte"
import { fs_rename, fs_trash, FSNode } from "lib/FilesystemAPI.svelte"
import { onMount } from "svelte"
import CreateDirectory from "./CreateDirectory.svelte"
import ListView from "./ListView.svelte"
@@ -15,6 +15,7 @@ import { FileAction, type FileActionHandler } from "./FileManagerLib";
import FileMenu from "./FileMenu.svelte";
import { loading_finish, loading_start } from "lib/Loading";
import SearchBar from "../SearchBar.svelte";
import type { GenericResponse } from "lib/NovaAPI";
let {
nav = $bindable(),
@@ -33,11 +34,11 @@ let {
} = $props();
let large_icons = $state(false)
let uploader: FsUploadWidget
let uploader!: FsUploadWidget
let mode = $state("viewing")
let creating_dir = $state(false)
let show_hidden = $state(false)
let file_menu: FileMenu = $state()
let file_menu!: FileMenu
export const upload = (files: File[]) => {
return uploader.upload_files(files)
@@ -119,12 +120,12 @@ const delete_selected = async () => {
loading_start()
// Save all promises with deletion requests in an array
let promises = []
let promises: Promise<GenericResponse>[] = []
nav.children.forEach(child => {
if (!child.fm_selected) {
return
}
promises.push(fs_delete_all(child.path))
promises.push(fs_trash(child.path))
})
// Wait for all the promises to finish
@@ -175,7 +176,7 @@ const toggle_large_icons = () => {
// Moving functions
let moving_items = []
let moving_items: FSNode[] = []
// We need to detect if shift is pressed so we can select multiple items
let shift_pressed = false
@@ -320,6 +321,14 @@ onMount(() => {
<button onclick={() => nav.reload()} title="Refresh directory listing">
<i class="icon">refresh</i>
</button>
{#if $nav.children.some(c => c.name === ".Trash" && c.type === "dir")}
<button
onclick={() => nav.navigate($nav.children.find(c => c.name === ".Trash").path, true)}
title="Open trash bin"
>
<i class="icon">delete</i>
</button>
{/if}
</div>
<div class="toolbar_middle">

View File

@@ -4,7 +4,7 @@ import type { FSNavigator } from "filesystem/FSNavigator";
import Button from "layout/Button.svelte";
import Dialog from "layout/Dialog.svelte";
import { bookmark_add, bookmark_del, bookmarks_store, is_bookmark } from "lib/Bookmarks";
import { fs_delete, type FSNode } from "lib/FilesystemAPI.svelte";
import { fs_trash, type FSNode } from "lib/FilesystemAPI.svelte";
import { loading_finish, loading_start } from "lib/Loading";
import { tick } from "svelte";
@@ -44,7 +44,7 @@ export const open = async (n: FSNode, target: EventTarget, event: Event) => {
const delete_node = async () => {
try {
loading_start()
await fs_delete(node.path)
await fs_trash(node.path)
nav.reload()
} catch (err) {
alert(JSON.stringify(err))

View File

@@ -26,8 +26,16 @@ let {
<thead>
<tr>
<td></td>
<td><SortButton active_field={$nav.sort_last_field} asc={$nav.sort_asc} sort_func={nav.sort_children} field="name">Name</SortButton></td>
<td class="hide_small"><SortButton active_field={$nav.sort_last_field} asc={$nav.sort_asc} sort_func={nav.sort_children} field="file_size">Size</SortButton></td>
<td>
<SortButton active_field={$nav.sort_last_field} asc={$nav.sort_asc} sort_func={nav.sort_children} field="name">
Name
</SortButton>
</td>
<td class="hide_small">
<SortButton active_field={$nav.sort_last_field} asc={$nav.sort_asc} sort_func={nav.sort_children} field="file_size">
Size
</SortButton>
</td>
<td></td>
</tr>
</thead>

View File

@@ -1,4 +1,4 @@
// Uploads a file to the logged in user's pixeldrain account. If no user is
// Uploads a file to the logged in user's Nova account. If no user is
// logged in the file is uploaded anonymously.
//
// on_progress reports progress on the file upload, parameter 1 is the uploaded

View File

@@ -32,7 +32,7 @@ export const update = async () => {
if (media_session) {
navigator.mediaSession.metadata = new MediaMetadata({
title: nav.base.name,
artist: "pixeldrain",
artist: "Nova",
album: "unknown",
});
}

View File

@@ -126,7 +126,7 @@ let magnet = $state("")
instructions for your torrent client to download the files from
other people who happen to be downloading the same files currently.
This means that instead of connecting to a single server (like
pixeldrain), you will be connecting to other people on the internet
Nova), you will be connecting to other people on the internet
to download these files.
</p>
<p>

View File

@@ -24,7 +24,7 @@ export const update = async () => {
if (media_session) {
navigator.mediaSession.metadata = new MediaMetadata({
title: node.name,
artist: "pixeldrain",
artist: "Nova",
album: "unknown",
});
console.debug("Updating media session")

View File

@@ -28,7 +28,7 @@ onMount(async () => {
{/snippet}
<p>
Your user account has been banned from uploading to
pixeldrain due to violation of the
Nova due to violation of the
<a href="/abuse">content policy</a>. Below is a list of
files originating from your account which have been blocked:
</p>
@@ -63,7 +63,7 @@ onMount(async () => {
</div>
<p>
If you would like to dispute your account ban you can mail me at
support@pixeldrain.com. Please do not mail unless you have a
support@nova.storage. Please do not mail unless you have a
good reason. If you do not provide a valid reason why the ban
should be reversed your e-mail will be ignored. And do not
forget to put your username ({window.user.username}) in the
@@ -87,7 +87,7 @@ onMount(async () => {
{#if result.ip_banned}
<p>
Your IP address ({result.address}) has been banned from
uploading to pixeldrain due to violation of the
uploading to Nova due to violation of the
<a href="/abuse">content policy</a>. Below is a list of
files originating from your IP address which have been
blocked:
@@ -96,7 +96,7 @@ onMount(async () => {
<p>
Your IP address ({result.address}) has received copyright
strikes. At 10 copyright strikes your IP address will be banned
and you will be unable to upload files to pixeldrain. Below is a
and you will be unable to upload files to Nova. Below is a
list of files originating from your IP address which have been
blocked:
</p>
@@ -151,7 +151,7 @@ onMount(async () => {
</p>
<p>
If you would like to dispute your IP ban you can mail me at
support@pixeldrain.com. Please do not mail unless you have a good
support@nova.storage. Please do not mail unless you have a good
reason. If you do not provide a valid reason why the IP ban should
be reversed your e-mail will be ignored. And do not forget to put
your IP address ({result.address}) in the e-mail.

View File

@@ -6,7 +6,7 @@ import OtherPlans from "./OtherPlans.svelte";
<section>
<p>
Pixeldrain features two different payment modes. We offer a monthly
Nova features two different payment modes. We offer a monthly
subscription which is managed by Patreon, and a Prepaid subscription
which supports a dozen different payment providers. With Prepaid you pay
in advance to charge your credit, then usage will be subtracted from
@@ -44,7 +44,7 @@ import OtherPlans from "./OtherPlans.svelte";
{/snippet}
The Pro subscription is managed by Patreon. Patreon's own fees
and sales tax will be added to this price. After paying you need
to link your pixeldrain account to Patreon to activate the plan.
to link your Nova account to Patreon to activate the plan.
</Tooltip>
</div>
<div class="feature_cell prepaid_feat">
@@ -224,13 +224,13 @@ import OtherPlans from "./OtherPlans.svelte";
<div class="bottom_row pro_feat">
{#if window.user.subscription.id === "patreon_1"}
You have this plan<br/>
Thank you for supporting pixeldrain!
Thank you for supporting Nova!
{:else}
<a href="https://www.patreon.com/join/pixeldrain/checkout?rid=5736701&cadence=1" class="button button_highlight round">
<a href="https://www.patreon.com/join/nova/checkout?rid=5736701&cadence=1" class="button button_highlight round">
€ 4 per month
</a>
or
<a href="https://www.patreon.com/join/pixeldrain/checkout?rid=5736701&cadence=12" class="button button_highlight round">
<a href="https://www.patreon.com/join/nova/checkout?rid=5736701&cadence=12" class="button button_highlight round">
€ 40 per year!
</a>
<br/>

View File

@@ -17,6 +17,11 @@ let upload_widget
<AddressReputation/>
<div class="page_content">
<div class="highlight_yellow">
This is a development server. All files and accounts may be lost when
the final product launches.
</div>
<section>
<p>
Nova.storage is a platform for cost-effective cloud storage and

View File

@@ -4,9 +4,9 @@
Persistence<br/>
{#if window.user.subscription.id === "patreon_2"}
You have this plan<br/>
Thank you for supporting pixeldrain!
Thank you for supporting Nova!
{:else}
<a href="https://www.patreon.com/join/pixeldrain/checkout?rid=5291482" class="button button_highlight round">
<a href="https://www.patreon.com/join/nova/checkout?rid=5291482" class="button button_highlight round">
€ 8
</a>
/ month
@@ -30,9 +30,9 @@
Tenacity<br/>
{#if window.user.subscription.id === "patreon_3"}
You have this plan<br/>
Thank you for supporting pixeldrain!
Thank you for supporting Nova!
{:else}
<a href="https://www.patreon.com/join/pixeldrain/checkout?rid=5291516" class="button button_highlight round">
<a href="https://www.patreon.com/join/nova/checkout?rid=5291516" class="button button_highlight round">
€ 16
</a>
/ month
@@ -51,9 +51,9 @@
Eternity<br/>
{#if window.user.subscription.id === "patreon_4"}
You have this plan<br/>
Thank you for supporting pixeldrain!
Thank you for supporting Nova!
{:else}
<a href="https://www.patreon.com/join/pixeldrain/checkout?rid=5291528" class="button button_highlight round">
<a href="https://www.patreon.com/join/nova/checkout?rid=5291528" class="button button_highlight round">
€ 32
</a>
/ month
@@ -72,9 +72,9 @@
Infinity<br/>
{#if window.user.subscription.id === "patreon_6"}
You have this plan<br/>
Thank you for supporting pixeldrain!
Thank you for supporting Nova!
{:else}
<a href="https://www.patreon.com/join/pixeldrain/checkout?rid=6573749" class="button button_highlight round">
<a href="https://www.patreon.com/join/nova/checkout?rid=6573749" class="button button_highlight round">
€ 64
</a>
/ month

View File

@@ -2,9 +2,9 @@
import Euro from "util/Euro.svelte";
import ProgressBar from "util/ProgressBar.svelte";
let fnx_storage = $state(0)
let fnx_egress = $state(0)
let fnx_total = $state(0)
let nova_storage = $state(0)
let nova_egress = $state(0)
let nova_total = $state(0)
let backblaze_storage = $state(0)
let backblaze_egress = $state(0)
let backblaze_api = $state(0)
@@ -20,9 +20,9 @@ let avg_file_size = $state(1000) // kB
$effect(() => {
// 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
fnx_total = fnx_storage + fnx_egress
nova_storage = Math.max(storage * 4, ((storage*10)/avg_file_size)*4)
nova_egress = egress * 1
nova_total = nova_storage + nova_egress
// Egress at Backblaze is free up to three times the amount of storage, then
// it's $10/TB
@@ -35,7 +35,7 @@ $effect(() => {
wasabi_storage = storage * 6.99
wasabi_total = (egress > storage) ? 0 : wasabi_storage
price_max = Math.max(fnx_total, backblaze_total, wasabi_total)
price_max = Math.max(nova_total, backblaze_total, wasabi_total)
});
</script>
@@ -67,10 +67,10 @@ $effect(() => {
<div class="bars">
<div>
<div>
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}/>
Nova.storage - <Euro amount={nova_total*1e6}/> / month<br/>
<Euro amount={nova_storage*1e6}/> storage,
<Euro amount={nova_egress*1e6}/> egress
<ProgressBar used={nova_total} total={price_max}/>
</div>
{#if avg_file_size < 10}
<div>

View File

@@ -3,10 +3,8 @@ import { onMount } from "svelte";
import Discord from "icons/Discord.svelte";
import Github from "icons/Github.svelte";
import Mastodon from "icons/Mastodon.svelte";
import Patreon from "icons/Patreon.svelte";
import Reddit from "icons/Reddit.svelte";
import { formatDataVolumeBits } from "util/Formatting";
import { get_endpoint, get_hostname } from "lib/PixeldrainAPI";
import { get_endpoint, get_hostname } from "lib/NovaAPI";
let { nobg = false }: {
nobg?: boolean;
@@ -34,20 +32,14 @@ onMount(async () => {
<footer class:nobg>
<div class="footer_content">
<div style="display: inline-block; margin: 0 8px;">
Pixeldrain is a product by
Nova is a product by
<a href="//fornaxian.tech" target="_blank" rel="noreferrer">Fornaxian Technologies</a>
</div>
<br/>
<div style="display: inline-block; margin: 0 8px;">
<a href="https://www.patreon.com/pixeldrain" target="_blank" rel="noreferrer">
<Patreon style="color: var(--body_text_color);"/> Patreon
</a> |
<a href="https://discord.gg/TWKGvYAFvX" target="_blank" rel="noreferrer">
<Discord style="color: var(--body_text_color);"/> Discord
</a> |
<a href="https://reddit.com/r/pixeldrain" target="_blank" rel="noreferrer">
<Reddit style="color: var(--body_text_color);"/> Reddit
</a> |
<a href="https://github.com/Fornaxian" target="_blank" rel="noreferrer">
<Github style="color: var(--body_text_color);"/> GitHub
</a> |

View File

@@ -4,7 +4,7 @@ import PickAmount from "./PickAmount.svelte";
import PickCountry from "./PickCountry.svelte";
import { payment_providers, type CheckoutState } from "./CheckoutLib";
import PickName from "./PickName.svelte";
import { get_misc_vat_rate, get_user } from "lib/PixeldrainAPI";
import { get_misc_vat_rate, get_user } from "lib/NovaAPI";
import { countries } from "country-data-list";
import PickProvider from "./PickProvider.svelte";

View File

@@ -1,5 +1,5 @@
import type { countries } from "country-data-list";
import { get_endpoint } from "lib/PixeldrainAPI";
import { get_endpoint } from "lib/NovaAPI";
export type CheckoutState = {
country: typeof countries.all[0]

View File

@@ -64,7 +64,7 @@ const submit = async (e: SubmitEvent) => {
</form>
<hr/>
<p style="text-align: initial;">
This Pixeldrain premium plan costs €1 per month, but due to
This Nova premium plan costs €1 per month, but due to
processing fees we can't accept payments less than €10. So your
deposit will give roughly 10 months of premium service depending on
usage. You can track your spending on the <a

View File

@@ -1,7 +1,7 @@
<script lang="ts">
import { preventDefault } from 'svelte/legacy';
import { countries } from "country-data-list";
import { get_misc_vat_rate, put_user } from "lib/PixeldrainAPI";
import { get_misc_vat_rate, put_user } from "lib/NovaAPI";
import { payment_providers, type CheckoutState } from "./CheckoutLib";
import { loading_finish, loading_start } from "lib/Loading";

View File

@@ -1,5 +1,5 @@
<script lang="ts">
import { put_user } from "lib/PixeldrainAPI";
import { put_user } from "lib/NovaAPI";
import { type CheckoutState } from "./CheckoutLib";
let { status = $bindable() }: {
@@ -35,11 +35,10 @@ const submit = async (e: SubmitEvent) => {
</form>
<hr/>
<p style="text-align: initial;">
This Pixeldrain premium plan costs €1 per month, but due to
processing fees we can't accept payments less than €10. So your
deposit will give roughly 10 months of premium service depending on
usage. You can track your spending on the <a
href="/user/prepaid/transactions">transactions page</a>.
This Nova premium plan costs €1 per month, but due to processing fees we
can't accept payments less than €10. So your deposit will give roughly 10
months of premium service depending on usage. You can track your spending on
the <a href="/user/prepaid/transactions">transactions page</a>.
</p>
<style>

View File

@@ -1,5 +1,5 @@
<script lang="ts">
import { put_user } from "lib/PixeldrainAPI";
import { put_user } from "lib/NovaAPI";
import { payment_providers, type CheckoutState, type PaymentProvider } from "./CheckoutLib";
let { status = $bindable() }: {

View File

@@ -1,5 +1,5 @@
import { countries } from "country-data-list"
import { check_response, get_endpoint } from "./PixeldrainAPI"
import { check_response, get_endpoint } from "./NovaAPI"
export const country_name = (country: string) => {
if (country !== "" && countries[country] !== undefined) {

View File

@@ -1,9 +1,9 @@
import { writable } from "svelte/store"
import { fs_check_response, fs_path_url, type FSNode } from "./FilesystemAPI.svelte"
import { loading_finish, loading_start } from "lib/Loading"
import { get_user } from "lib/PixeldrainAPI"
import { get_user } from "lib/NovaAPI"
const bookmarks_file = "/me/.fnx/bookmarks.json"
const bookmarks_file = "/me/.nova/bookmarks.json"
export type Bookmark = {
id: string,

View File

@@ -230,6 +230,29 @@ export const fs_delete_all = async (path: string) => {
) as GenericResponse
}
export const fs_trash = async (path: string) => {
return await fs_check_response(
await fetch(fs_path_url(path) + "?trash", { method: "DELETE" })
) as GenericResponse
}
export type TrashEntry = {
node: FSNode;
original_path: string;
deletion_date: string;
};
export const fs_get_trash = async (path: string) => {
let resp = await fs_check_response(
await fetch(fs_path_url(path) + "?trash")
) as TrashEntry[]
resp.forEach((entry, index) => {
resp[index].node = Object.assign(new FSNode(), entry.node)
})
return resp
};
export const fs_search = async (path: string, term: string, limit = 10) => {
return await fs_check_response(
await fetch(

View File

@@ -1,5 +1,5 @@
import { writable } from "svelte/store";
import { get_user, type Subscription, type User } from "./PixeldrainAPI";
import { get_user, type Subscription, type User } from "./NovaAPI";
export const user = writable(
{ subscription: {} as Subscription } as User,

View File

@@ -1,7 +1,7 @@
<script lang="ts">
import { createEventDispatcher, onMount } from "svelte";
import Form, { type FormConfig } from "util/Form.svelte"
import { check_response, get_endpoint } from "lib/PixeldrainAPI";
import { check_response, get_endpoint } from "lib/NovaAPI";
let dispatch = createEventDispatcher()

View File

@@ -1,6 +1,6 @@
<script lang="ts">
import Form, { type FormConfig } from "util/Form.svelte"
import { get_endpoint } from "lib/PixeldrainAPI";
import { get_endpoint } from "lib/NovaAPI";
let form: FormConfig = {
fields: [

View File

@@ -3,7 +3,7 @@ import TabMenu from "util/TabMenu.svelte";
import Register from "./Register.svelte";
import Login from "./Login.svelte";
import { onMount } from "svelte";
import { get_user } from "lib/PixeldrainAPI";
import { get_user } from "lib/NovaAPI";
let pages = [
{

View File

@@ -69,7 +69,7 @@ const reload_sheet = () => {
<div id="page_content" class="page_content">
<section>
<p>
You can change how pixeldrain looks! Your theme choice will
You can change how Nova looks! Your theme choice will
be saved in a cookie.
</p>
<h2>Theme</h2>
@@ -100,9 +100,9 @@ const reload_sheet = () => {
Classic 2022 style, with purple gradients
<br/>
<br/>
<input type="radio" id="style_classic" name="style"><label for="style_classic">Pixeldrain classic (gray)</label>
<input type="radio" id="style_classic" name="style"><label for="style_classic">Nova classic (gray)</label>
<br/>
Classic pre-2020 pixeldrain style, dark gray
Classic pre-2020 Nova style, dark gray
<br/>
<br/>
Other (experimental) themes
@@ -126,9 +126,9 @@ const reload_sheet = () => {
<br/>
<input type="radio" id="style_adwaita_light" name="style"><label for="style_adwaita_light">Adwaita light</label>
<br/><br/>
<input type="radio" id="style_pixeldrain98" name="style"><label for="style_pixeldrain98">Pixeldrain 98</label>
<input type="radio" id="style_nova98" name="style"><label for="style_nova98">Nova 98</label>
<br/>
<input type="radio" id="style_pixeldrain98_dark" name="style"><label for="style_pixeldrain98_dark">Pixeldrain 98 (dark)</label>
<input type="radio" id="style_nova98_dark" name="style"><label for="style_nova98_dark">Nova 98 (dark)</label>
<h2>Hue</h2>
<p>

View File

@@ -9,7 +9,7 @@ import Speedtest from "./Speedtest.svelte";
<section>
<h2>How does this work?</h2>
<p>
The speedtest measures the maximum download speed from pixeldrain's
The speedtest measures the maximum download speed from Nova's
servers to your computer. This speed is not affected by the daily
download limit for free users.
</p>
@@ -45,8 +45,8 @@ import Speedtest from "./Speedtest.svelte";
byte.
</p>
<p>
The third number shows the latency to the pixeldrain servers. This
is dependent on how far you are removed from the closest pixeldrain
The third number shows the latency to the Nova servers. This
is dependent on how far you are removed from the closest Nova
server. The lower the latency the faster your downloads will be,
generally. The number shows request latency and not ping latency.
HTTP requests have some overhead which means this latency number
@@ -65,7 +65,7 @@ import Speedtest from "./Speedtest.svelte";
because it stays within their network.
</p>
<p>
Pixeldrain does not have this luxury. Because our budget is very
Nova does not have this luxury. Because our budget is very
small we are only able to afford the cheapest bandwidth available.
This means that the data has to travel further and is more likely to
be throttled.
@@ -85,11 +85,11 @@ import Speedtest from "./Speedtest.svelte";
</p>
<ol>
<li>
Your ISP is limiting the connection speed to pixeldrain's
Your ISP is limiting the connection speed to Nova's
servers
</li>
<li>
The pixeldrain servers are overloaded
The Nova servers are overloaded
</li>
</ol>
<p>

View File

@@ -147,11 +147,11 @@ const logout = async (key) => {
<tr>
<td colspan="1">
{#if row.app_name === "website login"}
<img src="/res/img/pixeldrain_32.png" alt="Pixeldrain logo" class="app_icon"/>
Pixeldrain website
<img src="/res/img/nova_32.png" alt="Nova logo" class="app_icon"/>
Nova website
{:else if row.app_name === "website keys page"}
<i class="icon">vpn_key</i>
Pixeldrain keys page
Nova keys page
{:else if row.app_name === "sharex"}
<img src="/res/img/sharex.png" alt="ShareX logo" class="app_icon"/>
ShareX

View File

@@ -4,7 +4,7 @@ import CopyButton from "layout/CopyButton.svelte";
import Form from "util/Form.svelte";
import Button from "layout/Button.svelte";
import OtpSetup from "./OTPSetup.svelte";
import { put_user } from "lib/PixeldrainAPI";
import { put_user } from "lib/NovaAPI";
let affiliate_link = window.location.protocol+"//"+window.location.host + "?ref=" + encodeURIComponent(window.user.username)
let affiliate_deny = $state(false)
@@ -114,7 +114,7 @@ const affiliate_settings = {
type: "text",
default_value: window.user.affiliate_user_name,
description: `The affiliate user name can be the name of a
pixeldrain account you wish to support with your subscription.
Nova account you wish to support with your subscription.
The account will receive a fee of €0.50 for every month that
your premium plan is active. This does not cost you anything
extra.`,
@@ -142,7 +142,7 @@ let delete_account = {
type: "description",
description: `
<p>
When you delete your pixeldrain account you will be
When you delete your Nova account you will be
logged out on all of your devices. Your account will be
scheduled for deletion in seven days. If you log back in to your
account during those seven days the deletion will be canceled.
@@ -161,7 +161,7 @@ let delete_account = {
<p>
If you have an active Pro subscription you need to end that
separately through your Patreon account. Deleting your
pixeldrain account will not cancel the subscription.
Nova account will not cancel the subscription.
</p>`,
},
],
@@ -200,14 +200,14 @@ let delete_account = {
Your own affiliate link is
<a href="{affiliate_link}">{affiliate_link}</a>
<CopyButton small_icon text={affiliate_link}/>. Share this link
with premium pixeldrain users to gain commissions. You can use
with premium Nova users to gain commissions. You can use
the "?ref={encodeURIComponent(window.user.username)}" referral
code on download pages too. For a detailed description of the
affiliate program please check out the <a
href="/about#toc_12">Q&A page</a>.
</p>
<p>
Note that the link includes the name of your pixeldrain
Note that the link includes the name of your Nova
account. If you change your account name the link will stop
working and you might stop receiving commissions.
</p>

View File

@@ -1,7 +1,7 @@
<script lang="ts">
import { onMount } from "svelte";
import Modal from "util/Modal.svelte";
import { get_user, put_user } from "lib/PixeldrainAPI";
import { get_user, put_user } from "lib/NovaAPI";
import { loading_finish, loading_start } from "lib/Loading";
let { always = false }: {
@@ -74,8 +74,8 @@ const deny = () => {
<Modal bind:this={modal} title="Affiliate sponsoring request" width="700px">
<section>
<p>
Hi! {referral} wants you to sponsor their pixeldrain account. This
will give them €0.50 every month in pixeldrain prepaid credit. They
Hi! {referral} wants you to sponsor their Nova account. This
will give them €0.50 every month in Nova prepaid credit. They
can use this credit to get a discount on their file storage and
sharing costs. Here is a short summary of what this entails:
</p>
@@ -86,12 +86,12 @@ const deny = () => {
longer receive commissions.
</li>
<li>
Pixeldrain credit cannot be cashed out. So they are not earning
Nova credit cannot be cashed out. So they are not earning
real money with this.
</li>
<li>
This does not cost you any extra money. The commissions paid out
to the creator are paid for by pixeldrain itself.
to the creator are paid for by Nova itself.
</li>
<li>
You can change who you are sponsoring at any time on your <a

View File

@@ -134,7 +134,7 @@ onMount(() => {
<p>
This setting only applies to your account, others will still see the
download page when visiting your files. When this is enabled you will be
redirected to the file download API when clicking a pixeldrain link.
redirected to the file download API when clicking a Nova link.
This means that images, videos and PDF files will be opened directly in
your browser, and other files are immediately downloaded to your device.
This only works for single file links, not albums. You will need a Pro

View File

@@ -60,13 +60,13 @@ onMount(() => {
<h2>
Connect
<img src="/res/img/jdownloader.png" alt="JDownloader logo" class="app_icon_small"/>
JDownloader to your pixeldrain account
JDownloader to your Nova account
</h2>
<p>
JDownloader is a software program which makes it easier to download
things from the web. You can connect JDownloader to your pixeldrain
account to benefit from faster download speed and other pixeldrain
Pro features.
things from the web. You can connect JDownloader to your Nova
account to benefit from faster download speed and other Nova Pro
features.
</p>
<h3>Step 1: Install JDownloader</h3>
<p>
@@ -81,11 +81,11 @@ onMount(() => {
</div>
<h3>Step 3: Generate an app key</h3>
<p>
To connect JDownloader to pixeldrain you need to generate an API
To connect JDownloader to Nova you need to generate an API
key and enter it in JDownloader's Account Manager.
<br/>
<strong>Do not show the generated key to anyone</strong>, it can
be used to gain access to your pixeldrain account!
be used to gain access to your Nova account!
</p>
{#if !api_key}
@@ -121,46 +121,46 @@ onMount(() => {
</div>
<p>
Click Save and you're done! You can now download files from
pixeldrain with JDownloader.
Nova with JDownloader.
</p>
{:else if app_name === "sharex"}
<h2>
Connect
<img src="/res/img/sharex.png" alt="ShareX logo" class="app_icon_small"/>
ShareX to your pixeldrain account
ShareX to your Nova account
</h2>
<p>
ShareX is a Screen capture, file sharing and productivity tool.
Pixeldrain is supported as a custom uploader. You can <a
Nova is supported as a custom uploader. You can <a
href="https://getsharex.com/" target="_blank" rel="noreferrer">get
ShareX here</a>.
</p>
<p>
Here you can download our custom ShareX uploader which uses
pixeldrain to upload your files. This uploader is configured to
upload files to your personal pixeldrain account. <strong>Do not
Nova to upload your files. This uploader is configured to
upload files to your personal Nova account. <strong>Do not
share the configuration file with anyone</strong>, it contains
your account credentials.
</p>
<div class="center">
<a href="/misc/sharex/pixeldrain.com.sxcu" class="button button_highlight">
<a href="/misc/sharex/nova.storage.sxcu" class="button button_highlight">
<i class="icon small">save</i>
Download ShareX Uploader
</a>
</div>
<h3>Setting pixeldrain as default uploader</h3>
<h3>Setting Nova as default uploader</h3>
<p>
Download the uploader config and choose 'Open file'
<br/>
<img src="/res/img/sharex_download.png" style="max-width: 100%;" alt=""/><br/>
Set pixeldrain.com as active uploader. Choose Yes
Set nova.storage as active uploader. Choose Yes
<br/>
<img src="/res/img/sharex_default.png" style="max-width: 100%;" alt=""/><br/>
</p>
{:else}
<h2>Connect an app to your pixeldrain account</h2>
<h2>Connect an app to your Nova account</h2>
<ul>
<li>
<a href="?app=jdownloader" class="button">

View File

@@ -76,7 +76,7 @@ onMount(() => {
<section>
<h2 id="deposit">Deposit credit</h2>
<p>
Pixeldrain credit can be used for our Prepaid subscription plan, which
Nova credit can be used for our Prepaid subscription plan, which
is different from the Patreon plans. Instead of monthly limits, with
Prepaid there are no limits. You pay for what you use, at a rate of €4
per TB per month for storage and €1 per TB for data transfer. Your

View File

@@ -61,7 +61,7 @@ onMount(() => {
</p>
<p>
The list should be formatted as a list of domain names separated by a
space. Like this: 'pixeldrain.com google.com twitter.com'
space. Like this: 'nova.storage google.com twitter.com'
</p>
Domain names:<br/>
<form class="form_row" onsubmit={preventDefault(save_embed)}>

View File

@@ -30,7 +30,7 @@ let frac = $derived(used / total)
<p>
You have used all of your data cap. People can still download your
files, but premium features are disabled. This means that the
download page shows pixeldrain branding, people who download your
download page shows Nova branding, people who download your
files have a daily download limit and hotlinking is disabled.
</p>
@@ -51,7 +51,7 @@ let frac = $derived(used / total)
<p>
You have used {(frac*100).toFixed(0)}% of your data cap. If your
data runs out the premium features related to downloading will be
disabled. This means that the download page shows pixeldrain
disabled. This means that the download page shows Nova
branding, people who download your files have a daily download limit
and hotlinking is disabled.
</p>

View File

@@ -3,7 +3,7 @@ import { onMount } from "svelte";
import Button from "layout/Button.svelte";
import CopyButton from "layout/CopyButton.svelte";
import ToggleButton from "layout/ToggleButton.svelte";
import { check_response, get_endpoint, get_user, type User } from "lib/PixeldrainAPI";
import { check_response, get_endpoint, get_user, type User } from "lib/NovaAPI";
let user: User = $state(null)
let secret = $state("")

View File

@@ -31,23 +31,23 @@ onMount(() => {
{#if patreon_result !== ""}
{#if patreon_error === "patreon_authentication_denied"}
<div class="highlight_yellow">
Please press "Allow" when asked if pixeldrain can access your
Please press "Allow" when asked if Nova can access your
profile.
</div>
{:else if patreon_result === "error"}
<div class="highlight_red">
<p>
An error occurred while linking Patreon subscription. Check if
there are any Pixeldrain integrations under "Logged in with
there are any Nova integrations under "Logged in with
Patreon" on this page: <a
href="https://www.patreon.com/settings/apps">https://www.patreon.com/settings/apps</a>.
Try disconnecting all Pixeldrain logins and try again.
Try disconnecting all Nova logins and try again.
</p>
<li>
This can also happen if you canceled your Patreon membership
before upgrading your pixeldrain account. In that case, go to
before upgrading your Nova account. In that case, go to
the <a
href="https://www.patreon.com/pixeldrain/membership">memberships
href="https://www.patreon.com/nova/membership">memberships
page</a> and activate your membership again. If you already paid
in the last 30 days you will not be charged again.
</li>
@@ -88,17 +88,17 @@ onMount(() => {
You pledged without selecting a support tier. It happens
sometimes that people pledge an amount of money without
selecting a support tier. If you don't have a tier
pixeldrain won't know which subscription you should get,
Nova won't know which subscription you should get,
regardless of how much you paid. To fix this you can select
a tier from <a
href="https://www.patreon.com/pixeldrain/membership">the
href="https://www.patreon.com/nova/membership">the
memberships page</a> and proceed to checkout. If you already
pledged the right amount you will not have to pay again.
</li>
<li>
Or you have not pledged at all yet. In that case it's
simple: <a
href="https://www.patreon.com/pixeldrain/membership">go to
href="https://www.patreon.com/nova/membership">go to
Patreon</a> and purchase a membership.
</li>
</ol>
@@ -110,7 +110,7 @@ onMount(() => {
</div>
{:else if patreon_result === "success"}
<div class="highlight_green">
Success! Your Patreon pledge has been linked to your pixeldrain
Success! Your Patreon pledge has been linked to your Nova
account. You are now able to use Pro features.
</div>
{/if}

View File

@@ -12,7 +12,7 @@ import EmbeddingControls from "./EmbeddingControls.svelte";
import Dashboard from "./dashboard/Dashboard.svelte";
import AffiliatePrompt from "./AffiliatePrompt.svelte";
import { onMount } from "svelte";
import { get_user, type User } from "lib/PixeldrainAPI";
import { get_user, type User } from "lib/NovaAPI";
let pages: Tab[] = [
{

View File

@@ -4,7 +4,7 @@ import SuccessMessage from "util/SuccessMessage.svelte";
import PatreonActivationResult from "./PatreonActivationResult.svelte";
import { loading_finish, loading_start } from "lib/Loading";
import { user } from "lib/UserStore";
import { put_user } from "lib/PixeldrainAPI";
import { put_user } from "lib/NovaAPI";
let subscription = $state($user.subscription.id)
let subscription_type = $state($user.subscription.type)
@@ -31,7 +31,7 @@ const update = async (plan: string) => {
<div class="highlight_green">
<h2>Payment successful!</h2>
<p>
Thank you for supporting pixeldrain! The credit has been added
Thank you for supporting Nova! The credit has been added
to your account balance.
</p>
<p>
@@ -42,7 +42,7 @@ const update = async (plan: string) => {
before your credit is deposited. SEPA transfers can take up to
two working days for example. When the deposit is complete you
will receive an e-mail. If it takes too long, contact
support@pixeldrain.com.
support@nova.storage.
</p>
</div>
{:else if window.location.hash === "#order_expired"}
@@ -72,10 +72,10 @@ const update = async (plan: string) => {
Here you can switch between different subscription plans.
</p>
<p>
The Patreon subscription is managed by Patreon. Pixeldrain cannot modify
The Patreon subscription is managed by Patreon. Nova cannot modify
or end your subsciption. If you would like to cancel your Patreon plan
you can do that <a
href="https://www.patreon.com/settings/memberships/pixeldrain"
href="https://www.patreon.com/settings/memberships/nova"
target="_blank">on Patreon</a>.
</p>
<p>
@@ -96,7 +96,7 @@ const update = async (plan: string) => {
Patreon<br/>
{#if subscription_type === "patreon"}
Currently active<br/>
<a class="button" href="https://www.patreon.com/settings/memberships/pixeldrain" target="_blank">
<a class="button" href="https://www.patreon.com/settings/memberships/nova" target="_blank">
<i class="icon">settings</i>
Manage
</a>
@@ -110,7 +110,7 @@ const update = async (plan: string) => {
<div class="feat_normal round_tr" class:feat_highlight={subscription_type === "patreon"}>
<p>
This subscription is managed by Patreon. You will need to <a
href="https://www.patreon.com/pixeldrain/membership"
href="https://www.patreon.com/nova/membership"
target="_blank">purchase a plan on Patreon</a> before you
can activate this subscription. After your purchase you can
click the "Link Patreon" button and your account will be
@@ -144,7 +144,7 @@ const update = async (plan: string) => {
plan. If you currently have a Patreon subscription active,
then enabling prepaid will not cancel that subscription. You
can end your subscription <a
href="https://www.patreon.com/settings/memberships/pixeldrain"
href="https://www.patreon.com/settings/memberships/nova"
target="_blank">on Patreon.com</a>.
</p>
<ul>

View File

@@ -103,7 +103,7 @@ onMount(() => {
of days in a month (30.4375).
</p>
<p>
Example: If you have 2 TB stored on your pixeldrain account at €4 per TB
Example: If you have 2 TB stored on your Nova account at €4 per TB
then the daily charge will be:<br/>
2 TB * € 4 = € 8<br/>

View File

@@ -1,6 +1,6 @@
<script>
import Button from "layout/Button.svelte";
import { logout_user } from "lib/PixeldrainAPI";
import { logout_user } from "lib/NovaAPI";
</script>
<ul>
<li>Username: {window.user.username}</li>

View File

@@ -3,7 +3,7 @@ import { onMount } from "svelte";
import Chart from "util/Chart.svelte";
import { color_by_name } from "util/Util";
import { formatDataVolume, formatThousands } from "util/Formatting";
import { get_endpoint } from "lib/PixeldrainAPI";
import { get_endpoint } from "lib/NovaAPI";
let { card_size = 1 }: {
card_size?: number;

View File

@@ -50,7 +50,7 @@ import { formatDataVolume } from "util/Formatting";
{#if window.user.subscription.id !== ""}
<li>
Support: For questions related to your account you can send a
message to support@pixeldrain.com
message to support@nova.storage
</li>
{/if}
</ul>

View File

@@ -1,5 +1,5 @@
<script lang="ts">
import { get_endpoint, get_user, type User } from "lib/PixeldrainAPI";
import { get_endpoint, get_user, type User } from "lib/NovaAPI";
import { onMount } from "svelte";
import HotlinkProgressBar from "user_home/HotlinkProgressBar.svelte";
import StorageProgressBar from "user_home/StorageProgressBar.svelte";

View File

@@ -26,7 +26,7 @@ export type SubmitResult = {
<script lang="ts">
import { onMount } from "svelte";
import Spinner from "./Spinner.svelte";
import type { GenericResponse } from "lib/PixeldrainAPI";
import type { GenericResponse } from "lib/NovaAPI";
let { config }: {
config: FormConfig;

View File

@@ -13,7 +13,7 @@ import { fs_get_node } from "lib/FilesystemAPI.svelte";
import { css_from_path } from "filesystem/edit_window/Branding";
import { loading_run, loading_store } from "lib/Loading";
import Spinner from "util/Spinner.svelte";
import { get_user } from "lib/PixeldrainAPI";
import { get_user } from "lib/NovaAPI";
import Tree from "./Tree.svelte";
import MenuEntry from "./MenuEntry.svelte";
import { writable } from "svelte/store";
@@ -206,6 +206,10 @@ const set_offset = (off: number) => {
<i class="icon">folder</i>
<span>Filesystem</span>
</a>
<a class="button" href="/d/me/.Trash" use:highlight_current_page>
<i class="icon">delete</i>
<span>Trash</span>
</a>
<a class="button" href="/user" use:highlight_current_page>
<i class="icon">person</i>
<span>Account</span>

View File

@@ -10,7 +10,7 @@ import SpeedtestPage from "speedtest/SpeedtestPage.svelte";
import Appearance from "pages/Appearance.svelte";
import Footer from "layout/Footer.svelte";
import { current_page_store, type Tab } from "./RouterStore";
import { get_user, type User } from "lib/PixeldrainAPI";
import { get_user, type User } from "lib/NovaAPI";
import { breadcrumbs_store } from "./BreadcrumbStore";
let pages: Tab[] = [

View File

@@ -24,7 +24,7 @@ export default defineConfig({
sourcemap: !production,
lib: {
entry: "src/wrap.js",
name: "fnx_web",
name: "nova_web",
fileName: name,
}
},