211 lines
6.6 KiB
HTML
211 lines
6.6 KiB
HTML
<!DOCTYPE html>
|
|
<html lang="en">
|
|
<head>
|
|
<meta charset="UTF-8">
|
|
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
|
<meta name="theme-color" content="#3b82f6">
|
|
<meta name="apple-mobile-web-app-capable" content="yes">
|
|
<meta name="apple-mobile-web-app-status-bar-style" content="black-translucent">
|
|
<link rel="manifest" href="/manifest.json">
|
|
{% load static %}
|
|
<link rel="icon" href="data:image/svg+xml,<svg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 100 100'><text y='.9em' font-size='90'>📁</text></svg>">
|
|
<link rel="apple-touch-icon" href="{% static 'portal/icon-192.png' %}">
|
|
<title>{% block title %}Upload{% endblock %} - rfiles.online</title>
|
|
<style>
|
|
:root {
|
|
--bg: #0a0a0a;
|
|
--surface: #141414;
|
|
--surface-hover: #1a1a1a;
|
|
--border: #2a2a2a;
|
|
--text: #e0e0e0;
|
|
--text-muted: #888;
|
|
--primary: #3b82f6;
|
|
--primary-hover: #2563eb;
|
|
--success: #22c55e;
|
|
--error: #ef4444;
|
|
}
|
|
|
|
* {
|
|
box-sizing: border-box;
|
|
margin: 0;
|
|
padding: 0;
|
|
}
|
|
|
|
body {
|
|
font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, sans-serif;
|
|
background: var(--bg);
|
|
color: var(--text);
|
|
min-height: 100vh;
|
|
line-height: 1.5;
|
|
}
|
|
|
|
.container {
|
|
max-width: 1200px;
|
|
margin: 0 auto;
|
|
padding: 2rem;
|
|
}
|
|
|
|
header {
|
|
display: flex;
|
|
justify-content: space-between;
|
|
align-items: center;
|
|
margin-bottom: 2rem;
|
|
padding-bottom: 1rem;
|
|
border-bottom: 1px solid var(--border);
|
|
}
|
|
|
|
header h1 {
|
|
font-size: 1.5rem;
|
|
font-weight: 600;
|
|
}
|
|
|
|
header nav a {
|
|
color: var(--text-muted);
|
|
text-decoration: none;
|
|
margin-left: 1.5rem;
|
|
transition: color 0.2s;
|
|
}
|
|
|
|
header nav a:hover, header nav a.active {
|
|
color: var(--text);
|
|
}
|
|
|
|
.btn {
|
|
display: inline-flex;
|
|
align-items: center;
|
|
gap: 0.5rem;
|
|
padding: 0.5rem 1rem;
|
|
border: none;
|
|
border-radius: 6px;
|
|
font-size: 0.875rem;
|
|
font-weight: 500;
|
|
cursor: pointer;
|
|
transition: all 0.2s;
|
|
text-decoration: none;
|
|
}
|
|
|
|
.btn-primary {
|
|
background: var(--primary);
|
|
color: white;
|
|
}
|
|
|
|
.btn-primary:hover {
|
|
background: var(--primary-hover);
|
|
}
|
|
|
|
.btn-ghost {
|
|
background: transparent;
|
|
color: var(--text-muted);
|
|
border: 1px solid var(--border);
|
|
}
|
|
|
|
.btn-ghost:hover {
|
|
background: var(--surface);
|
|
color: var(--text);
|
|
}
|
|
|
|
.btn-danger {
|
|
background: var(--error);
|
|
color: white;
|
|
}
|
|
|
|
.card {
|
|
background: var(--surface);
|
|
border: 1px solid var(--border);
|
|
border-radius: 8px;
|
|
padding: 1.5rem;
|
|
margin-bottom: 1rem;
|
|
}
|
|
|
|
.text-muted { color: var(--text-muted); }
|
|
.text-success { color: var(--success); }
|
|
.text-error { color: var(--error); }
|
|
.mt-1 { margin-top: 0.5rem; }
|
|
.mt-2 { margin-top: 1rem; }
|
|
.mb-1 { margin-bottom: 0.5rem; }
|
|
.mb-2 { margin-bottom: 1rem; }
|
|
</style>
|
|
{% block extra_css %}{% endblock %}
|
|
</head>
|
|
<body>
|
|
<div class="container">
|
|
<header>
|
|
<h1>rfiles.online</h1>
|
|
<nav>
|
|
<a href="{% url 'portal:upload' %}" class="{% if request.resolver_match.url_name == 'upload' %}active{% endif %}">Upload</a>
|
|
<a href="{% url 'portal:files' %}" class="{% if request.resolver_match.url_name == 'files' %}active{% endif %}">Files</a>
|
|
<a href="/admin/" target="_blank">Admin</a>
|
|
</nav>
|
|
</header>
|
|
|
|
{% block content %}{% endblock %}
|
|
</div>
|
|
|
|
{% block extra_js %}{% endblock %}
|
|
|
|
<script>
|
|
if ('serviceWorker' in navigator) {
|
|
navigator.serviceWorker.register('/sw.js', { scope: '/' })
|
|
.then((registration) => {
|
|
console.log('SW registered:', registration.scope);
|
|
})
|
|
.catch((error) => {
|
|
console.log('SW registration failed:', error);
|
|
});
|
|
}
|
|
|
|
const params = new URLSearchParams(window.location.search);
|
|
if (params.get('shared') === 'files') {
|
|
const count = params.get('count') || 1;
|
|
showNotification(`${count} file(s) uploaded successfully!`, 'success');
|
|
history.replaceState({}, '', '/');
|
|
} else if (params.get('shared') === 'true') {
|
|
const url = params.get('url');
|
|
const text = params.get('text');
|
|
const title = params.get('title');
|
|
if (url || text) {
|
|
showSharePreview(title, text, url);
|
|
}
|
|
history.replaceState({}, '', '/');
|
|
} else if (params.get('queued') === 'true') {
|
|
showNotification('Saved for upload when back online', 'info');
|
|
history.replaceState({}, '', '/');
|
|
}
|
|
|
|
function showNotification(message, type) {
|
|
const notif = document.createElement('div');
|
|
notif.className = 'pwa-notification ' + type;
|
|
notif.textContent = message;
|
|
notif.style.cssText = `
|
|
position: fixed;
|
|
top: 1rem;
|
|
right: 1rem;
|
|
padding: 1rem 1.5rem;
|
|
border-radius: 8px;
|
|
background: ${type === 'success' ? '#22c55e' : type === 'info' ? '#3b82f6' : '#ef4444'};
|
|
color: white;
|
|
font-weight: 500;
|
|
z-index: 10000;
|
|
animation: slideIn 0.3s ease;
|
|
`;
|
|
document.body.appendChild(notif);
|
|
setTimeout(() => notif.remove(), 4000);
|
|
}
|
|
|
|
function showSharePreview(title, text, url) {
|
|
const content = [title, text, url].filter(Boolean).join('\n\n');
|
|
if (content) {
|
|
showNotification('Shared content received! Create a note or save the URL.', 'info');
|
|
sessionStorage.setItem('sharedContent', JSON.stringify({ title, text, url }));
|
|
}
|
|
}
|
|
</script>
|
|
<style>
|
|
@keyframes slideIn {
|
|
from { transform: translateX(100%); opacity: 0; }
|
|
to { transform: translateX(0); opacity: 1; }
|
|
}
|
|
</style>
|
|
</body>
|
|
</html>
|