// Firebase Configuration
const firebaseConfig = {
apiKey: "YOUR_API_KEY",
authDomain: "YOUR_PROJECT_ID.firebaseapp.com",
databaseURL: "https://YOUR_PROJECT_ID-default-rtdb.firebaseio.com",
projectId: "YOUR_PROJECT_ID",
storageBucket: "YOUR_PROJECT_ID.appspot.com",
messagingSenderId: "YOUR_SENDER_ID",
appId: "YOUR_APP_ID"
};
// Initialize Firebase
firebase.initializeApp(firebaseConfig);
const storage = firebase.storage();
const database = firebase.database();
// App State
let selectedFile = null;
// DOM Elements
const app = document.getElementById('app');
const toast = document.getElementById('toast');
const progressModal = document.getElementById('progressModal');
const uploadProgress = document.getElementById('uploadProgress');
const progressText = document.getElementById('progressText');
// Hash Router
const routes = {
'/': renderUploadPage,
'/files': renderFilesPage,
'/file/:id': renderDownloadPage
};
// Initialize App
document.addEventListener('DOMContentLoaded', () => {
handleRoute();
window.addEventListener('hashchange', handleRoute);
document.getElementById('homeLink').addEventListener('click', () => {
window.location.hash = '#/';
});
});
function handleRoute() {
const hash = window.location.hash.slice(1) || '/';
const path = hash.split('?')[0];
document.querySelectorAll('.nav-link').forEach(link => {
const route = link.dataset.route;
link.classList.toggle('active', path === route);
});
if (path.startsWith('/file/')) {
const id = path.split('/')[2];
renderDownloadPage(id);
} else if (routes[path]) {
routes[path]();
} else {
routes['/']();
}
}
// Utility Functions
function showToast(message, type = 'info') {
toast.textContent = message;
toast.className = `toast show ${type}`;
setTimeout(() => {
toast.classList.remove('show');
}, 3000);
}
function formatBytes(bytes) {
if (bytes === 0) return '0 Bytes';
const k = 1024;
const sizes = ['Bytes', 'KB', 'MB', 'GB'];
const i = Math.floor(Math.log(bytes) / Math.log(k));
return parseFloat((bytes / Math.pow(k, i)).toFixed(2)) + ' ' + sizes[i];
}
function generateShortId() {
return Math.random().toString(36).substring(2, 8) +
Math.random().toString(36).substring(2, 8);
}
// Render Upload Page
function renderUploadPage() {
const html = `
Drop files anywhere
or click to select
`;
app.innerHTML = html;
initializeUploadPage();
}
function initializeUploadPage() {
const dropZone = document.getElementById('dropZone');
const fileInput = document.getElementById('fileInput');
const selectFileBtn = document.getElementById('selectFileBtn');
const uploadBtn = document.getElementById('uploadBtn');
const selectedFileContainer = document.getElementById('selectedFileContainer');
const selectedFileName = document.getElementById('selectedFileName');
const selectedFileSize = document.getElementById('selectedFileSize');
dropZone.addEventListener('click', () => fileInput.click());
dropZone.addEventListener('dragover', (e) => {
e.preventDefault();
dropZone.classList.add('dragover');
});
dropZone.addEventListener('dragleave', () => {
dropZone.classList.remove('dragover');
});
dropZone.addEventListener('drop', (e) => {
e.preventDefault();
dropZone.classList.remove('dragover');
const file = e.dataTransfer.files[0];
if (file) handleFileSelect(file);
});
fileInput.addEventListener('change', (e) => {
const file = e.target.files[0];
if (file) handleFileSelect(file);
});
selectFileBtn.addEventListener('click', () => fileInput.click());
uploadBtn.addEventListener('click', () => {
if (!selectedFile) {
showToast('Please select a file first', 'error');
return;
}
uploadFile(selectedFile);
});
function handleFileSelect(file) {
selectedFile = file;
selectedFileName.textContent = file.name;
selectedFileSize.textContent = formatBytes(file.size);
selectedFileContainer.style.display = 'block';
}
}
// Upload File (No auth required)
async function uploadFile(file) {
const shortId = generateShortId();
const timestamp = Date.now();
const safeFileName = file.name.replace(/[^a-zA-Z0-9.-]/g, '_');
const storageRef = storage.ref(`uploads/${timestamp}_${safeFileName}`);
const uploadTask = storageRef.put(file);
progressModal.style.display = 'block';
uploadTask.on('state_changed',
(snapshot) => {
const progress = (snapshot.bytesTransferred / snapshot.totalBytes) * 100;
uploadProgress.style.width = progress + '%';
progressText.textContent = Math.round(progress) + '%';
},
(error) => {
console.error('Upload error:', error);
progressModal.style.display = 'none';
showToast('Upload failed. Please try again.', 'error');
},
async () => {
try {
const downloadURL = await uploadTask.snapshot.ref.getDownloadURL();
// Save file info to Realtime Database (no user data)
const fileData = {
id: shortId,
name: file.name,
size: file.size,
type: file.type || 'application/octet-stream',
url: downloadURL,
shortId: shortId,
timestamp: timestamp,
downloads: 0,
storagePath: `uploads/${timestamp}_${safeFileName}`
};
await database.ref(`files/${shortId}`).set(fileData);
// Also add to public file list for easy browsing
await database.ref(`public-files/${shortId}`).set({
id: shortId,
name: file.name,
timestamp: timestamp
});
progressModal.style.display = 'none';
uploadProgress.style.width = '0%';
const fileUrl = `${window.location.origin}${window.location.pathname}#/file/${shortId}`;
showToast('File uploaded successfully!', 'success');
// Ask user if they want to copy link
if (confirm('File uploaded! Copy link to clipboard?')) {
navigator.clipboard.writeText(fileUrl);
showToast('Link copied to clipboard!', 'success');
}
// Reset UI
selectedFile = null;
document.getElementById('selectedFileContainer').style.display = 'none';
document.getElementById('fileInput').value = '';
} catch (error) {
console.error('Database error:', error);
progressModal.style.display = 'none';
showToast('Error saving file info', 'error');
}
}
);
}
// Render Files Page (Public files - no auth needed)
async function renderFilesPage() {
app.innerHTML = 'Loading files...
';
try {
// Get all public files
const filesSnapshot = await database.ref('files').once('value');
const filesData = filesSnapshot.val() || {};
const files = Object.values(filesData)
.sort((a, b) => b.timestamp - a.timestamp)
.slice(0, 50); // Show only 50 most recent files
if (files.length === 0) {
app.innerHTML = `
`;
return;
}
const filesHtml = `
${files.map(file => `
`).join('')}
`;
app.innerHTML = filesHtml;
} catch (error) {
console.error('Error loading files:', error);
app.innerHTML = `
Error loading files. Please try again.
`;
}
}
// Copy link function (global)
window.copyLink = async function(shortId) {
const link = `${window.location.origin}${window.location.pathname}#/file/${shortId}`;
try {
await navigator.clipboard.writeText(link);
showToast('Link copied to clipboard!', 'success');
} catch (err) {
// Fallback for older browsers
const textarea = document.createElement('textarea');
textarea.value = link;
document.body.appendChild(textarea);
textarea.select();
document.execCommand('copy');
document.body.removeChild(textarea);
showToast('Link copied to clipboard!', 'success');
}
};
// Render Download Page
async function renderDownloadPage(fileId) {
app.innerHTML = 'Loading file info...
';
try {
const fileSnapshot = await database.ref(`files/${fileId}`).once('value');
const fileData = fileSnapshot.val();
if (!fileData) {
app.innerHTML = `
File not found or has been removed
Go Home
`;
return;
}
// Increment download count
await database.ref(`files/${fileId}/downloads`).transaction(count => (count || 0) + 1);
const html = `
`;
app.innerHTML = html;
} catch (error) {
console.error('Error loading file:', error);
app.innerHTML = `
Error loading file. Please try again.
Go Home
`;
}
}