Skip to content

Commit 7f3a811

Browse files
committed
improved UI and some fixes
1 parent 7e64e1d commit 7f3a811

File tree

8 files changed

+155
-2370
lines changed

8 files changed

+155
-2370
lines changed

.gitignore

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2,4 +2,4 @@
22
node_modules
33
pnpm-lock.yaml
44
package-lock.json
5-
m.js
5+
yarn.lock

README.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -74,6 +74,7 @@ CACHE_TTL=3600 # Cache duration in seconds
7474
MAX_REQUESTS=100 # Max upload requests in specific time
7575
RATE_LIMIT=1 minute # 100 req per minute
7676
```
77+
Note: If you change `AUTH_TOKEN` then update it in public/script.js at line `189`
7778

7879
## Starting the Server
7980

api/index.js

Lines changed: 18 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -2,8 +2,8 @@ const fastifyRateLimit = require("@fastify/rate-limit");
22
const fastifyMultipart = require("@fastify/multipart");
33
const FileType = require("file-type");
44
const stream = require("stream");
5-
const { runtime, formatBytes } = require("@nexoracle/utils");
6-
require("dotenv").config();
5+
const { runtime, formatBytes, env } = require("@nexoracle/utils");
6+
env.load();
77
const mega = require("../mega.js");
88
const config = require("../config.js");
99
const fastify = require("fastify")({ logger: 0 });
@@ -17,7 +17,7 @@ fastify.register(require("@fastify/static"), {
1717

1818
fastify.register(fastifyRateLimit, config.rateLimit);
1919
fastify.register(fastifyMultipart, {
20-
limits: { fileSize: 1024 * 1024 * config.server.maxFileSize, files: config.server.maxFiles },
20+
limits: { fileSize: 1024 * 1024 * Number(config.server.maxFileSize), files: Number(config.server.maxFiles) },
2121
});
2222

2323
fastify.addHook("onSend", (request, reply, payload, done) => {
@@ -123,6 +123,21 @@ fastify.get("/media/*", async (request, reply) => {
123123
}
124124
});
125125

126+
fastify.get("/info", async (request, reply) => {
127+
const info = {
128+
request_limit: config.rateLimit.max,
129+
rate_limit: config.rateLimit.timeWindow,
130+
file_size: config.server.maxFileSize,
131+
max_files: config.server.maxFiles,
132+
};
133+
134+
if (config.autoDelete.enable === true) {
135+
info.auto_delete_time = config.autoDelete.minutes;
136+
}
137+
138+
return reply.send(info);
139+
});
140+
126141
var start = async () => {
127142
try {
128143
await mega.initialize();

package.json

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -23,9 +23,8 @@
2323
"@fastify/multipart": "^9.0.3",
2424
"@fastify/rate-limit": "^10.2.2",
2525
"@fastify/static": "^8.1.1",
26-
"@nexoracle/utils": "^1.1.18",
26+
"@nexoracle/utils": "github:nexoracle/utils",
2727
"async-mutex": "^0.5.0",
28-
"dotenv": "^16.5.0",
2928
"fastify": "^5.2.1",
3029
"file-type": "^16.5.4",
3130
"megajs": "^1.3.5",

public/index.html

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -38,6 +38,15 @@ <h1>The fastest way to transfer <span class="highlight">large files</span></h1>
3838

3939
<div class="awesome-container">
4040
<div class="upload-box">
41+
<div class="info-icon" id="uploadInfoIcon">
42+
<i class="fas fa-info-circle"></i>
43+
<div class="info-tooltip" id="infoTooltip">
44+
<div class="tooltip-content">
45+
<p>Loading upload limits...</p>
46+
</div>
47+
</div>
48+
</div>
49+
4150
<div class="drag-zone" id="dragZone">
4251
<i class="fa fa-cloud-upload-alt drag-icon"></i>
4352
<div class="drag-text">Drag & drop files here</div>

public/script.js

Lines changed: 53 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -22,6 +22,34 @@ document.addEventListener("DOMContentLoaded", function () {
2222
const fileList = document.getElementById("fileList");
2323
const dragZone = document.getElementById("dragZone");
2424
const folderUploadBtn = document.getElementById("folderUpload");
25+
const infoIcon = document.getElementById("uploadInfoIcon");
26+
const infoTooltip = document.getElementById("infoTooltip");
27+
const tooltipContent = infoTooltip.querySelector(".tooltip-content");
28+
29+
infoIcon.addEventListener("click", () => {
30+
infoTooltip.classList.toggle("active");
31+
});
32+
33+
document.addEventListener("click", (e) => {
34+
if (!infoIcon.contains(e.target)) {
35+
infoTooltip.classList.remove("active");
36+
}
37+
});
38+
39+
fetch("/info")
40+
.then((response) => response.json())
41+
.then((data) => {
42+
tooltipContent.innerHTML = `
43+
<p><i class="fas fa-tachometer-alt"></i>${data.request_limit} requests in ${data.rate_limit}</p>
44+
<p><i class="fas fa-file-alt"></i>${data.file_size}MB max file size</p>
45+
<p><i class="fas fa-copy"></i>Max ${data.max_files} files can be uploaded</p>
46+
${data.auto_delete_time ? `<p><i class="fas fa-clock"></i>Auto deletes after ${formatMinutes(data.auto_delete_time)}</p>` : ""}
47+
`;
48+
})
49+
.catch((error) => {
50+
tooltipContent.innerHTML = `<p>Error loading config info</p>`;
51+
console.error("Error fetching config info:", error);
52+
});
2553

2654
folderUploadBtn.addEventListener("click", function () {
2755
const input = document.createElement("input");
@@ -247,4 +275,29 @@ document.addEventListener("DOMContentLoaded", function () {
247275
}, 300);
248276
}, 3000);
249277
}
278+
279+
function formatMinutes(minutes) {
280+
minutes = Number.parseInt(minutes, 10);
281+
282+
if (isNaN(minutes)) return "unknown time";
283+
284+
if (minutes < 60) {
285+
return `${minutes} minute${minutes !== 1 ? "s" : ""}`;
286+
} else if (minutes < 24 * 60) {
287+
const hours = Math.floor(minutes / 60);
288+
return `${hours} hour${hours !== 1 ? "s" : ""}`;
289+
} else if (minutes < 7 * 24 * 60) {
290+
const days = Math.floor(minutes / (24 * 60));
291+
return `${days} day${days !== 1 ? "s" : ""}`;
292+
} else if (minutes < 30 * 24 * 60) {
293+
const weeks = Math.floor(minutes / (7 * 24 * 60));
294+
return `${weeks} week${weeks !== 1 ? "s" : ""}`;
295+
} else if (minutes < 365 * 24 * 60) {
296+
const months = Math.floor(minutes / (30 * 24 * 60));
297+
return `${months} month${months !== 1 ? "s" : ""}`;
298+
} else {
299+
const years = Math.floor(minutes / (365 * 24 * 60));
300+
return `${years} year${years !== 1 ? "s" : ""}`;
301+
}
302+
}
250303
});

public/styles.css

Lines changed: 72 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -83,6 +83,7 @@ header {
8383
}
8484

8585
.upload-box {
86+
position: relative;
8687
background: rgba(30, 30, 30, 0.7);
8788
backdrop-filter: blur(10px);
8889
padding: 30px 40px;
@@ -339,6 +340,67 @@ footer {
339340
color: #ff416c;
340341
}
341342

343+
.info-icon {
344+
position: absolute;
345+
top: 15px;
346+
right: 15px;
347+
color: rgba(255, 255, 255, 0.7);
348+
font-size: 18px;
349+
cursor: pointer;
350+
transition: color 0.2s ease;
351+
z-index: 10;
352+
}
353+
354+
.info-icon:hover {
355+
color: #ff416c;
356+
}
357+
358+
.info-tooltip {
359+
position: absolute;
360+
top: 100%;
361+
right: 0;
362+
width: 250px;
363+
background: rgba(30, 30, 30, 0.95);
364+
border-radius: 8px;
365+
padding: 12px;
366+
box-shadow: 0 5px 15px rgba(0, 0, 0, 0.3);
367+
backdrop-filter: blur(10px);
368+
border: 1px solid rgba(255, 255, 255, 0.1);
369+
color: #fff;
370+
font-size: 14px;
371+
text-align: left;
372+
z-index: 100;
373+
opacity: 0;
374+
visibility: hidden;
375+
transform: translateY(10px);
376+
transition: all 0.3s ease;
377+
}
378+
379+
.info-icon:hover .info-tooltip,
380+
.info-tooltip.active {
381+
opacity: 1;
382+
visibility: visible;
383+
transform: translateY(5px);
384+
}
385+
386+
.tooltip-content {
387+
display: flex;
388+
flex-direction: column;
389+
gap: 8px;
390+
}
391+
392+
.tooltip-content p {
393+
margin: 0;
394+
display: flex;
395+
align-items: center;
396+
}
397+
398+
.tooltip-content i {
399+
margin-right: 8px;
400+
width: 16px;
401+
text-align: center;
402+
}
403+
342404
@keyframes slideIn {
343405
from {
344406
transform: translateX(100%);
@@ -380,6 +442,11 @@ footer {
380442
.file-name {
381443
max-width: 200px;
382444
}
445+
446+
.info-icon {
447+
top: 24px;
448+
right: 28px;
449+
}
383450
}
384451

385452
@media (max-width: 480px) {
@@ -409,6 +476,11 @@ footer {
409476
.hero h1 {
410477
font-size: 1.5rem;
411478
}
479+
480+
.info-icon {
481+
top: 20px;
482+
right: 24px;
483+
}
412484
}
413485

414486
.file-list::-webkit-scrollbar {

0 commit comments

Comments
 (0)