Files
app_compartir/web/templates/viewer.html
T

229 lines
12 KiB
HTML

{{template "base.html" .}}
{{define "title"}}{{.Share.Title}} — Visor de app_compartir{{end}}
{{define "content"}}
<div class="max-w-4xl mx-auto space-y-6">
<!-- Header Card -->
<div class="bg-slate-900 border border-slate-800 rounded-3xl p-5 sm:p-6 shadow-xl flex flex-col md:flex-row md:items-center justify-between gap-4">
<div class="space-y-1.5 min-w-0">
<div class="flex flex-wrap items-center gap-2">
<h1 class="text-xl sm:text-2xl font-bold text-white truncate max-w-lg" title="{{.Share.Title}}">
{{.Share.Title}}
</h1>
{{if .Share.IsGuest}}
<span class="px-2.5 py-0.5 rounded-full text-xs font-semibold bg-amber-500/10 border border-amber-500/20 text-amber-400">
<i class="fa-regular fa-clock mr-1"></i> Caduca en 24h
</span>
{{else}}
<span class="px-2.5 py-0.5 rounded-full text-xs font-semibold bg-emerald-500/10 border border-emerald-500/20 text-emerald-400">
<i class="fa-solid fa-shield mr-1"></i> Permanente
</span>
{{end}}
</div>
<div class="flex flex-wrap items-center gap-x-4 gap-y-1 text-xs text-slate-400">
<span><i class="fa-solid fa-user text-slate-500 mr-1"></i> {{.Share.UserDisplay}}</span>
{{if ne .Share.Type "text"}}
<span><i class="fa-solid fa-hard-drive text-slate-500 mr-1"></i> {{.Share.FormattedSize}}</span>
{{end}}
<span><i class="fa-solid fa-eye text-slate-500 mr-1"></i> {{.Share.ViewsCount}} visitas</span>
<span><i class="fa-solid fa-calendar-day text-slate-500 mr-1"></i> {{.FormattedDate}}</span>
</div>
</div>
<!-- Action buttons -->
<div class="flex items-center gap-2 shrink-0">
{{if ne .Share.Type "text"}}
<a href="/d/{{.Share.ID}}" class="px-4 py-2 rounded-xl bg-brand-600 hover:bg-brand-500 text-slate-950 font-bold text-sm transition flex items-center gap-1.5 shadow-lg shadow-brand-500/20">
<i class="fa-solid fa-download"></i>
<span>Descargar</span>
</a>
<a href="/raw/{{.Share.ID}}" target="_blank" class="p-2.5 rounded-xl bg-slate-800 hover:bg-slate-700 text-slate-300 border border-slate-700 transition" title="Ver archivo original / raw">
<i class="fa-solid fa-arrow-up-right-from-square"></i>
</a>
{{else}}
<button onclick="copyTextContent()" id="copyTextBtn" class="px-4 py-2 rounded-xl bg-brand-600 hover:bg-brand-500 text-slate-950 font-bold text-sm transition flex items-center gap-1.5 shadow-lg shadow-brand-500/20">
<i class="fa-regular fa-copy"></i>
<span id="copyTextBtnLabel">Copiar texto</span>
</button>
{{end}}
<button onclick="toggleQRModal()" class="p-2.5 rounded-xl bg-slate-800 hover:bg-slate-700 text-slate-300 border border-slate-700 transition" title="Ver código QR para móvil">
<i class="fa-solid fa-qrcode"></i>
</button>
<button onclick="copyCurrentURL()" class="p-2.5 rounded-xl bg-slate-800 hover:bg-slate-700 text-slate-300 border border-slate-700 transition" title="Copiar enlace">
<i class="fa-solid fa-link"></i>
</button>
</div>
</div>
<!-- Viewer Body -->
<div class="bg-slate-900 border border-slate-800 rounded-3xl p-4 sm:p-6 shadow-2xl overflow-hidden">
{{if .IsImage}}
<!-- Image Viewer -->
<div class="flex flex-col items-center justify-center space-y-3">
<div class="relative group max-h-[80vh] flex items-center justify-center rounded-2xl overflow-hidden bg-slate-950/60 p-2 border border-slate-800/80">
<img id="viewerImage" src="/raw/{{.Share.ID}}" alt="{{.Share.Title}}" class="max-h-[75vh] w-auto max-w-full object-contain rounded-xl shadow-lg transition-transform duration-200">
</div>
<div class="flex items-center gap-2">
<button onclick="toggleImageZoom()" class="px-3 py-1.5 rounded-lg bg-slate-800 hover:bg-slate-700 text-xs text-slate-300 border border-slate-700 transition flex items-center gap-1.5">
<i class="fa-solid fa-magnifying-glass-plus text-brand-400"></i>
<span id="zoomBtnLabel">Zoom 100%</span>
</button>
<a href="/raw/{{.Share.ID}}" target="_blank" class="px-3 py-1.5 rounded-lg bg-slate-800 hover:bg-slate-700 text-xs text-slate-300 border border-slate-700 transition flex items-center gap-1.5">
<i class="fa-solid fa-expand text-brand-400"></i>
<span>Pantalla Completa</span>
</a>
</div>
</div>
{{else if .IsVideo}}
<!-- Video Viewer -->
<div class="rounded-2xl overflow-hidden bg-black border border-slate-800 flex items-center justify-center">
<video controls autoplay playsinline class="w-full max-h-[75vh] rounded-2xl">
<source src="/raw/{{.Share.ID}}" type="{{.Share.MimeType}}">
Tu navegador no soporta la reproducción de video HTML5.
</video>
</div>
{{else if .IsAudio}}
<!-- Audio Viewer -->
<div class="p-8 sm:p-12 flex flex-col items-center justify-center space-y-6 bg-slate-950/60 rounded-2xl border border-slate-800/80">
<div class="w-20 h-20 rounded-3xl bg-brand-500/10 border border-brand-500/20 text-brand-400 flex items-center justify-center text-3xl shadow-xl shadow-brand-500/10 animate-pulse">
<i class="fa-solid fa-music"></i>
</div>
<div class="text-center space-y-1">
<h3 class="text-lg font-bold text-white">{{.Share.Title}}</h3>
<p class="text-xs text-slate-400">{{.Share.FormattedSize}} • {{.Share.MimeType}}</p>
</div>
<div class="w-full max-w-md">
<audio controls autoplay class="w-full">
<source src="/raw/{{.Share.ID}}" type="{{.Share.MimeType}}">
Tu navegador no soporta audio HTML5.
</audio>
</div>
</div>
{{else if .IsPDF}}
<!-- PDF Viewer -->
<div class="space-y-3">
<div class="w-full h-[80vh] rounded-2xl overflow-hidden border border-slate-800 bg-slate-950">
<iframe src="/raw/{{.Share.ID}}" class="w-full h-full border-none">
Tu navegador no soporta iframe para PDFs. <a href="/raw/{{.Share.ID}}" class="text-brand-400 underline">Haz clic para descargarlo</a>.
</iframe>
</div>
</div>
{{else if or (eq .Share.Type "text") .IsText}}
<!-- Text / Code Viewer -->
<div class="relative space-y-2">
<div class="flex items-center justify-between text-xs text-slate-400 px-1">
<span><i class="fa-solid fa-file-lines mr-1 text-slate-500"></i> Formato de texto</span>
<span>{{len .Share.TextContent}} caracteres</span>
</div>
<div class="relative group">
<pre id="rawTextContent" class="p-5 rounded-2xl bg-slate-950 border border-slate-800 font-mono text-xs sm:text-sm text-slate-100 overflow-x-auto whitespace-pre-wrap leading-relaxed custom-scrollbar selection:bg-brand-500 selection:text-black">{{.Share.TextContent}}</pre>
</div>
</div>
{{else}}
<!-- Generic File Download Card -->
<div class="p-10 sm:p-14 flex flex-col items-center justify-center space-y-6 text-center bg-slate-950/60 rounded-2xl border border-slate-800/80">
<div class="w-20 h-20 rounded-3xl bg-slate-800 border border-slate-700 text-slate-300 flex items-center justify-center text-3xl shadow-xl">
<i class="fa-solid fa-file-zipper"></i>
</div>
<div class="space-y-1">
<h3 class="text-lg font-bold text-white max-w-md break-all">{{.Share.Title}}</h3>
<p class="text-xs text-slate-400">{{.Share.FormattedSize}} • {{.Share.MimeType}}</p>
</div>
<a href="/d/{{.Share.ID}}" class="px-6 py-3 rounded-xl bg-brand-600 hover:bg-brand-500 text-slate-950 font-bold text-sm transition flex items-center gap-2 shadow-lg shadow-brand-500/20">
<i class="fa-solid fa-download"></i>
<span>Descargar archivo ahora</span>
</a>
</div>
{{end}}
</div>
<!-- Quick Share QR Drawer for Mobile -->
<div class="bg-slate-900 border border-slate-800 rounded-3xl p-5 flex flex-col sm:flex-row items-center justify-between gap-4">
<div class="flex items-center gap-3 text-center sm:text-left">
<div class="w-10 h-10 rounded-xl bg-brand-500/10 border border-brand-500/20 text-brand-400 flex items-center justify-center text-lg shrink-0">
<i class="fa-solid fa-mobile-screen"></i>
</div>
<div>
<p class="text-sm font-semibold text-white">¿Quieres abrir esto en tu teléfono?</p>
<p class="text-xs text-slate-400">Escanea el código QR sin enviar mensajes por WhatsApp</p>
</div>
</div>
<div class="flex items-center gap-3">
<img src="/qr/{{.Share.ID}}" alt="QR Code" class="w-16 h-16 rounded-lg bg-white p-1 shadow">
<button onclick="toggleQRModal()" class="px-3.5 py-2 rounded-xl bg-slate-800 hover:bg-slate-700 text-xs font-semibold text-slate-200 border border-slate-700 transition">
Ver QR en grande
</button>
</div>
</div>
</div>
<!-- QR Modal -->
<div id="qrModal" class="hidden fixed inset-0 z-50 bg-slate-950/80 backdrop-blur-sm flex items-center justify-center p-4">
<div class="bg-slate-900 border border-slate-800 rounded-3xl p-6 max-w-sm w-full space-y-4 text-center shadow-2xl animate-fade-in">
<div class="flex items-center justify-between">
<h3 class="text-base font-bold text-white">Escanea con tu teléfono</h3>
<button onclick="toggleQRModal()" class="text-slate-400 hover:text-white p-1"><i class="fa-solid fa-xmark"></i></button>
</div>
<div class="p-3 bg-white rounded-2xl shadow-inner inline-block">
<img src="/qr/{{.Share.ID}}" alt="Código QR grande" class="w-56 h-56 object-contain">
</div>
<p class="text-xs text-slate-400">Apunta la cámara de tu móvil para abrir este visor directamente.</p>
<button onclick="toggleQRModal()" class="w-full py-2.5 rounded-xl bg-slate-800 hover:bg-slate-700 text-sm font-semibold text-white transition">
Cerrar
</button>
</div>
</div>
{{end}}
{{define "scripts"}}
<script>
let isZoomed = false;
function toggleImageZoom() {
const img = document.getElementById('viewerImage');
const label = document.getElementById('zoomBtnLabel');
if (!img) return;
isZoomed = !isZoomed;
if (isZoomed) {
img.classList.remove('max-h-[75vh]');
img.classList.add('max-h-none', 'scale-110');
label.innerText = 'Restablecer';
} else {
img.classList.add('max-h-[75vh]');
img.classList.remove('max-h-none', 'scale-110');
label.innerText = 'Zoom 100%';
}
}
function toggleQRModal() {
const modal = document.getElementById('qrModal');
modal.classList.toggle('hidden');
}
function copyCurrentURL() {
navigator.clipboard.writeText(window.location.href).then(() => {
alert('¡Enlace copiado al portapapeles!');
});
}
function copyTextContent() {
const text = document.getElementById('rawTextContent').innerText;
navigator.clipboard.writeText(text).then(() => {
const btn = document.getElementById('copyTextBtnLabel');
btn.innerText = '¡Copiado!';
setTimeout(() => {
btn.innerText = 'Copiar texto';
}, 2000);
});
}
</script>
{{end}}