first commit

This commit is contained in:
Simon
2026-01-28 16:02:57 +00:00
commit 3a9011690c
6 changed files with 260 additions and 0 deletions

106
frontend/app.js Normal file
View File

@@ -0,0 +1,106 @@
let currentPage = 1;
const perPage = 12;
localStorage.clear();
function InitializeLocalStorage() {
if (!localStorage.getItem('config')) {
localStorage.setItem('config', JSON.stringify({ servers: [{ "https://getfigleaf.com": {} }] }));
InitializeServerStatus();
}
}
function InitializeServerStatus() {
const config = JSON.parse(localStorage.getItem('config'));
config.servers.forEach(serverObj => {
const server = Object.keys(serverObj)[0];
fetch(`/api/status`, {
method: "POST",
body: JSON.stringify({ server: server }),
headers: {
"Content-Type": "application/json",
},
})
.then(response => response.json())
.then(status => {
serverObj[server] = status;
localStorage.setItem('config', JSON.stringify(config));
})
.catch(err => {
serverObj[server] = { online: false };
localStorage.setItem('config', JSON.stringify(config));
});
});
}
async function loadVideos() {
const config = JSON.parse(localStorage.getItem('config'));
const response = await fetch('/api/videos', {
method: 'POST',
headers: { 'Content-Type': 'application/json' },
body: JSON.stringify({
channel: config.channel,
sort: "latest",
query: "",
page: currentPage,
perPage: perPage
})
});
const videos = await response.json();
renderVideos(videos);
currentPage++;
}
function renderVideos(videos) {
const grid = document.getElementById('video-grid');
videos.forEach(v => {
const card = document.createElement('div');
card.className = 'video-card';
card.innerHTML = `
<img src="${v.thumb}" alt="${v.title}">
<h4>${v.title}</h4>
<p>${v.channel}${v.duration}s</p>
`;
card.onclick = () => openPlayer(v.url);
grid.appendChild(card);
});
}
function openPlayer(videoUrl) {
const modal = document.getElementById('video-modal');
const player = document.getElementById('player');
// Using GET for the video tag src as it's the standard for streaming
player.src = `/api/stream?url=${encodeURIComponent(videoUrl)}`;
modal.style.display = 'block';
}
function closePlayer() {
const modal = document.getElementById('video-modal');
const player = document.getElementById('player');
player.pause();
player.src = "";
modal.style.display = 'none';
}
// UI Helpers
function toggleDrawer(id) {
document.querySelectorAll('.drawer').forEach(d => d.classList.remove('open'));
document.getElementById(`drawer-${id}`).classList.add('open');
document.getElementById('overlay').style.display = 'block';
}
function closeDrawers() {
document.querySelectorAll('.drawer').forEach(d => d.classList.remove('open'));
document.getElementById('overlay').style.display = 'none';
}
// Infinite Scroll Observer
const observer = new IntersectionObserver((entries) => {
if (entries[0].isIntersecting) loadVideos();
}, { threshold: 1.0 });
observer.observe(document.getElementById('sentinel'));
// Init
InitializeLocalStorage();
loadVideos();