Files
Oxicloud/static/js/views/public/publicShare.js
T
2026-05-07 22:43:02 +02:00

131 lines
5.3 KiB
JavaScript

import { oxiIconsInit } from '../../core/icons';
/**
* publicShare.js — Client-side logic for the public share page (/s/{token}).
*
* Fetches share metadata from the API, handles password-protected shares,
* and renders file download or folder info.
*/
(() => {
// ── DOM refs ───────────────────────────────────────────────────
const $loading = document.getElementById('share-loading');
const $password = document.getElementById('share-password');
const $expired = document.getElementById('share-expired');
const $file = document.getElementById('share-file');
const $folder = document.getElementById('share-folder');
const $pwForm = document.getElementById('password-form');
const $pwInput = document.getElementById('password-input');
const $pwError = document.getElementById('password-error');
const $fileName = document.getElementById('file-name');
const $fileMeta = document.getElementById('file-meta');
const $fileDl = document.getElementById('file-download');
const $folderName = document.getElementById('folder-name');
const $expiredMsg = document.getElementById('expired-message');
// ── Extract token from URL path (/s/{token}) ──────────────────
const pathParts = window.location.pathname.split('/');
const tokenIdx = pathParts.indexOf('s');
const TOKEN = tokenIdx !== -1 ? pathParts[tokenIdx + 1] : null;
oxiIconsInit();
if (!TOKEN) {
showState('expired');
$expiredMsg.textContent = 'Invalid share link.';
return;
}
// ── Helpers ────────────────────────────────────────────────────
function showState(name) {
[$loading, $password, $expired, $file, $folder].forEach((el) => {
el.classList.add('hidden');
});
var target = {
loading: $loading,
password: $password,
expired: $expired,
file: $file,
folder: $folder
}[name];
if (target) target.classList.remove('hidden');
}
// ── Render share data ─────────────────────────────────────────
function renderShare(data) {
if (data.item_type === 'folder') {
$folderName.textContent = data.item_name || 'Shared Folder';
showState('folder');
} else {
$fileName.textContent = data.item_name || 'Shared File';
$fileMeta.textContent = data.item_name ? 'Shared file' : '';
$fileDl.href = `/api/s/${TOKEN}/download`;
showState('file');
}
}
// ── Fetch share metadata ──────────────────────────────────────
function fetchShare() {
fetch(`/api/s/${encodeURIComponent(TOKEN)}`)
.then((res) => {
if (res.ok) return res.json();
if (res.status === 401) {
return res.json().then((body) => {
if (body?.requiresPassword) {
showState('password');
return null;
}
throw new Error('Unauthorized');
});
}
if (res.status === 410) {
showState('expired');
return null;
}
throw new Error(`HTTP ${res.status}`);
})
.then((data) => {
if (data) renderShare(data);
})
.catch(() => {
showState('expired');
$expiredMsg.textContent = 'This share link is no longer available.';
});
}
// ── Password form ─────────────────────────────────────────────
$pwForm.addEventListener('submit', (e) => {
e.preventDefault();
$pwError.classList.add('hidden');
var password = $pwInput.value;
if (!password) return;
fetch(`/api/s/${encodeURIComponent(TOKEN)}/verify`, {
method: 'POST',
headers: { 'Content-Type': 'application/json' },
body: JSON.stringify({ password: password })
})
.then((res) => {
if (res.ok) return res.json();
if (res.status === 401) {
$pwError.textContent = 'Incorrect password. Please try again.';
$pwError.classList.remove('hidden');
return null;
}
throw new Error(`HTTP ${res.status}`);
})
.then((data) => {
if (data) renderShare(data);
})
.catch(() => {
$pwError.textContent = 'An error occurred. Please try again.';
$pwError.classList.remove('hidden');
});
});
// ── Init ──────────────────────────────────────────────────────
fetchShare();
})();