Add info tooltips to the feature table

This commit is contained in:
2025-03-27 15:10:59 +01:00
parent 0de8754d9b
commit 28aa8142ca
7 changed files with 184 additions and 47 deletions

View File

@@ -6,9 +6,9 @@
Files will be removed if they have not been accessed for 120 days. When a file Files will be removed if they have not been accessed for 120 days. When a file
is downloaded the expiry time is reset to 120 days from the current day. This is downloaded the expiry time is reset to 120 days from the current day. This
only happens when someone downloads more than 1% of the whole file in a single only happens when someone downloads more than 10% of the whole file in a single
request. So if you have a 5 GB file the timer is only extended when you download request. So if you have a 5 GB file the timer is only extended when you download
at least 50 MB. The expiry timer is not updated when it was already updated at least 500 MB. The expiry timer is not updated when it was already updated
within the last 24 hours. within the last 24 hours.
File expiry is often seen as a downside of pixeldrain. But keep in mind that 120 File expiry is often seen as a downside of pixeldrain. But keep in mind that 120

View File

@@ -20,7 +20,7 @@
"@babel/preset-env": "^7.26.0", "@babel/preset-env": "^7.26.0",
"@rollup/plugin-babel": "^6.0.4", "@rollup/plugin-babel": "^6.0.4",
"@rollup/plugin-commonjs": "^26.0.3", "@rollup/plugin-commonjs": "^26.0.3",
"@rollup/plugin-node-resolve": "^15.3.0", "@rollup/plugin-node-resolve": "^15.3.1",
"@rollup/plugin-terser": "^0.4.4", "@rollup/plugin-terser": "^0.4.4",
"@rollup/plugin-typescript": "^11.1.6", "@rollup/plugin-typescript": "^11.1.6",
"@types/jsmediatags": "^3.9.6", "@types/jsmediatags": "^3.9.6",
@@ -1718,9 +1718,9 @@
} }
}, },
"node_modules/@rollup/plugin-node-resolve": { "node_modules/@rollup/plugin-node-resolve": {
"version": "15.3.0", "version": "15.3.1",
"resolved": "https://registry.npmjs.org/@rollup/plugin-node-resolve/-/plugin-node-resolve-15.3.0.tgz", "resolved": "https://registry.npmjs.org/@rollup/plugin-node-resolve/-/plugin-node-resolve-15.3.1.tgz",
"integrity": "sha512-9eO5McEICxMzJpDW9OnMYSv4Sta3hmt7VtBFz5zR9273suNOydOyq/FrGeGy+KsTRFm8w0SLVhzig2ILFT63Ag==", "integrity": "sha512-tgg6b91pAybXHJQMAAwW9VuWBO6Thi+q7BCNARLwSqlmsHz0XYURtGvh/AuwSADXSI4h/2uHbs7s4FzlZDGSGA==",
"dev": true, "dev": true,
"license": "MIT", "license": "MIT",
"dependencies": { "dependencies": {

View File

@@ -11,7 +11,7 @@
"@babel/preset-env": "^7.26.0", "@babel/preset-env": "^7.26.0",
"@rollup/plugin-babel": "^6.0.4", "@rollup/plugin-babel": "^6.0.4",
"@rollup/plugin-commonjs": "^26.0.3", "@rollup/plugin-commonjs": "^26.0.3",
"@rollup/plugin-node-resolve": "^15.3.0", "@rollup/plugin-node-resolve": "^15.3.1",
"@rollup/plugin-terser": "^0.4.4", "@rollup/plugin-terser": "^0.4.4",
"@rollup/plugin-typescript": "^11.1.6", "@rollup/plugin-typescript": "^11.1.6",
"@types/jsmediatags": "^3.9.6", "@types/jsmediatags": "^3.9.6",

View File

@@ -55,11 +55,11 @@ export default [
extensions: ['.svelte'], extensions: ['.svelte'],
}), }),
commonjs(), commonjs(),
nodeResolve(), nodeResolve({
typescript({ modulePaths: [process.cwd() + "/src"],
compilerOptions: { lib: ["es2015", "dom"] }, extensions: [".svelte", ".mjs", ".js", ".json"]
verbatimModuleSyntax: true,
}), }),
typescript(),
// Watch the `public` directory and refresh the browser on changes when // Watch the `public` directory and refresh the browser on changes when
// not in production // not in production

View File

@@ -1,4 +1,5 @@
<script> <script>
import Tooltip from "layout/Tooltip.svelte";
import Euro from "../util/Euro.svelte"; import Euro from "../util/Euro.svelte";
import OtherPlans from "./OtherPlans.svelte"; import OtherPlans from "./OtherPlans.svelte";
</script> </script>
@@ -34,45 +35,76 @@ import OtherPlans from "./OtherPlans.svelte";
<span class="bold">None</span> <span class="bold">None</span>
</div> </div>
<div class="feature_cell pro_feat"> <div class="feature_cell pro_feat">
<span class="bold">€4 / month</span> or <Tooltip>
<span class="bold">€40 / year</span><br/> <span slot="label">
Charged through Patreon <span class="bold">€4 / month</span> or
<span class="bold">€40 / year</span>
</span>
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.
</Tooltip>
</div> </div>
<div class="feature_cell prepaid_feat"> <div class="feature_cell prepaid_feat">
<span class="bold">€1 / month minimum</span><br/> <Tooltip>
Only charged when usage is less than €1 <span slot="label" class="bold">€1 / month minimum</span>
<p>
The minimum fee is only charged when usage is less than €1.
This calculation is per day, the €1 amount is divided by the
number of days in the month and if your usage is lower than
that, you will be charged the minimum fee.
</p>
</Tooltip>
</div> </div>
<div class="left_col"> <div class="left_col">
<a class="round button" href="/about#toc_3"> <a href="/about#toc_3">Transfer limit</a>
<i class="icon">info</i>
Transfer limit
</a>
</div> </div>
<div class="feature_cell free_feat"> <div class="feature_cell free_feat">
<span class="bold">6 GB per day</span><br/> <Tooltip>
<span slot="label" class="bold">6 GB per day</span>
Download speed is reduced to 1 MiB/s when exceeded. Max 3 concurrent <p>
downloads Free users are limited to downloading 6 GB per day, this
limit is linked to your IP address, even if you are logged
in to an account.
</p>
<p>
When the download limit is exceeded the download speed is
reduced to 1 MiB/s. You can have at most three concurrent
downloads running.
</p>
</Tooltip>
</div> </div>
<div class="feature_cell pro_feat"> <div class="feature_cell pro_feat">
<span class="bold">4 TB per 30 days</span><br/> <Tooltip>
<span slot="label" class="bold">4 TB per 30 days</span>
Transfer limit is used for downloading, sharing and hotlinking. No <p>
connection limit The transfer limit is used for downloading, sharing and
hotlinking files.
</p>
<p>
Paid plans do not have a concurrent connection limit.
</p>
</Tooltip>
</div> </div>
<div class="feature_cell prepaid_feat"> <div class="feature_cell prepaid_feat">
<span class="bold">€1 per TB transferred</span><br/> <Tooltip>
<span slot="label" class="bold">€1 per TB transferred</span>
Used for downloading, sharing and hotlinking. You only pay for what <p>
you use. No connection limit Prepaid does not have a transfer limit, instead you are
charged for what you use at a rate of €1 per terabyte
downloaded. This applies to downloading your own files,
other people's files and others downloading your files (if
you have hotlinking enabled in your account settings).
</p>
<p>
Paid plans do not have a concurrent connection limit.
</p>
</Tooltip>
</div> </div>
<div class="left_col"> <div class="left_col">
<a class="round button" href="/about#toc_6"> <a href="/about#toc_6">Hotlinking</a>
<i class="icon">info</i>
Hotlinking
</a>
</div> </div>
<div class="feature_cell free_feat"> <div class="feature_cell free_feat">
<span class="bold">Hotlinking not supported</span><br/> <span class="bold">Hotlinking not supported</span><br/>
@@ -92,25 +124,55 @@ import OtherPlans from "./OtherPlans.svelte";
</div> </div>
<div class="feature_cell prepaid_feat"> <div class="feature_cell prepaid_feat">
<span class="bold">€4 / TB / month</span><br/> <span class="bold">€4 / TB / month</span><br/>
No limit, you only pay for what you use No limit, you pay for what you use
</div> </div>
<div class="left_col"> <div class="left_col">
<a class="round button" href="/about#toc_1"> <a href="/about#toc_1">File expiry</a>
<i class="icon">info</i>
File expiry
</a>
</div> </div>
<div class="feature_cell free_feat"> <div class="feature_cell free_feat">
<span class="bold">120 days</span> (4 months) <Tooltip>
<span slot="label" class="bold">120 days (4 months)</span>
<p>
Files expire when they have not been downloaded in the last
120 days. A download is counted when more than 10% of the
whole file was downloaded in a single request.
</p>
</Tooltip>
</div> </div>
<div class="feature_cell pro_feat"> <div class="feature_cell pro_feat">
<span class="bold">240 days</span> (8 months)<br/> <Tooltip>
Plans without expiry are available <span slot="label" class="bold">240 days (8 months)</span>
<p>
The Pro plan has 240 day file expiry. The same rules apply
as the free plan. Higher Patreon subscription plans are
available where files do not expire at all.
</p>
</Tooltip>
</div> </div>
<div class="feature_cell prepaid_feat"> <div class="feature_cell prepaid_feat">
<span class="bold">Files do not expire</span><br/> <Tooltip>
While prepaid subscription plan is active <span slot="label" class="bold">Files do not expire</span>
<p>
Files don't expire while your Prepaid plan is active. If
your credit runs out you have one week to top up your
balance. If you fail to do so your files will revert to the
regular file expiry rules.
</p>
</Tooltip>
</div>
<div class="left_col">
Download page customization
</div>
<div class="feature_cell free_feat">
<span class="bold">None</span>
</div>
<div class="feature_cell pro_feat">
None
</div>
<div class="feature_cell prepaid_feat">
Theme, background, header and footer image can be customized
</div> </div>
<div class="left_col"> <div class="left_col">

View File

@@ -0,0 +1,71 @@
<script lang="ts">
let button: HTMLButtonElement
let dialog: HTMLDialogElement
export let style = ""
const open = () => {
// Show the window so we can get the location
dialog.showModal()
const edge_offset = 5
// Get the egdes of the screen, so the window does not spawn off-screen
const window_rect = dialog.getBoundingClientRect()
const max_left = window.innerWidth - window_rect.width - edge_offset
const max_top = window.innerHeight - window_rect.height - edge_offset
// Get the location of the button
const button_rect = button.getBoundingClientRect()
// Prevent the window from being glued to the edges
const min_left = Math.max((button_rect.left + (button_rect.width/2)) - (window_rect.width/2), edge_offset)
const min_top = Math.max(button_rect.bottom, edge_offset)
// Place the window
dialog.style.left = Math.round(Math.min(min_left, max_left)) + "px"
dialog.style.top = Math.round(Math.min(min_top, max_top)) + "px"
}
// Close the dialog when the user clicks the background
const click = (e: Event) => {
if (e.target === dialog) {
dialog.close()
}
}
</script>
<button bind:this={button} on:click={open} class="button round" style={style}>
<i class="icon">info</i><slot name="label"></slot>
</button>
<!-- svelte-ignore a11y-click-events-have-key-events -->
<!-- svelte-ignore a11y-no-noninteractive-element-interactions -->
<dialog bind:this={dialog} on:click={click}>
<div class="menu">
<slot></slot>
</div>
</dialog>
<style>
.button {
flex: 0 0 content;
box-shadow: none;
}
dialog {
text-align: initial;
background-color: var(--card_color);
color: var(--body_text_color);
border-radius: 8px;
border: none;
padding: 0.5em;
margin: 0;
box-shadow: 2px 2px 10px var(--shadow_color);
}
.menu {
display: flex;
flex-direction: column;
max-width: 20em;
}
</style>

View File

@@ -1,6 +1,10 @@
{ {
"compilerOptions": { "compilerOptions": {
"baseUrl": "./", "lib": [
"es2015",
"dom"
],
"baseUrl": "./src",
"verbatimModuleSyntax": true, "verbatimModuleSyntax": true,
"target": "ES2017", "target": "ES2017",
}, },