added tracking

This commit is contained in:
2025-12-07 19:43:40 +01:00
parent 8fa40218e5
commit 2dcc2f425e
5 changed files with 146 additions and 8 deletions

View File

@@ -113,10 +113,16 @@ function renderContinueWatching(id, list) {
const el = document.createElement('div');
el.className = 'card';
el.onclick = () => window.location.href =
item.source === 'anilist'
? `/anime/${item.entry_id}`
: `/anime/${item.source}/${item.entry_id}`;
el.onclick = () => {
const ep = item.progress || 1;
if (item.source === 'anilist') {
window.location.href = `http://localhost:54322/watch/${item.entry_id}/${ep}`;
} else {
window.location.href = `http://localhost:54322/watch/${item.entry_id}/${ep}?${item.source}`;
}
};
const progressText = item.total_episodes
? `${item.progress || 0}/${item.total_episodes}`

View File

@@ -350,6 +350,20 @@ function playVideo(url, subtitles = []) {
settings: ['captions', 'quality', 'speed']
});
let alreadyTriggered = false;
video.addEventListener('timeupdate', () => {
if (!video.duration) return;
const percent = (video.currentTime / video.duration) * 100;
if (percent >= 80 && !alreadyTriggered) {
alreadyTriggered = true;
sendProgress();
}
});
video.play().catch(() => console.log("Autoplay blocked"));
}
@@ -378,6 +392,40 @@ if (currentEpisode <= 1) {
document.getElementById('prev-btn').disabled = true;
}
async function sendProgress() {
const token = localStorage.getItem('token');
if (!token) return;
const source = extName
? extName
: "anilist";
const body = {
entry_id: animeId,
source: source,
entry_type: "ANIME",
status: 'CURRENT',
progress: source === 'anilist'
? Math.floor(currentEpisode)
: currentEpisode
};
try {
await fetch('/api/list/entry', {
method: 'POST',
headers: {
'Content-Type': 'application/json',
'Authorization': `Bearer ${token}`
},
body: JSON.stringify(body)
});
} catch (err) {
console.error('Error updating progress:', err);
}
}
loadMetadata();
loadExtensions();

View File

@@ -39,6 +39,23 @@ function getSimpleAuthHeaders() {
};
}
function applyChapterFromUrlFilter() {
const params = new URLSearchParams(window.location.search);
const chapterParam = params.get('chapter');
if (!chapterParam) return;
const chapterNumber = parseFloat(chapterParam);
if (isNaN(chapterNumber)) return;
filteredChapters = allChapters.filter(
ch => parseFloat(ch.number) === chapterNumber
);
currentPage = 1;
}
function getBookEntryType(bookData) {
if (!bookData) return 'MANGA';
@@ -449,6 +466,7 @@ async function loadChapters(idForFetch) {
allChapters = data.chapters || [];
filteredChapters = [...allChapters];
applyChapterFromUrlFilter();
const totalEl = document.getElementById('total-chapters');

View File

@@ -241,10 +241,16 @@ function renderContinueReading(id, list) {
const el = document.createElement('div');
el.className = 'card';
el.onclick = () => window.location.href =
item.source === 'anilist'
? `/book/${item.entry_id}`
: `/book/${item.source}/${item.entry_id}`;
el.onclick = () => {
const ch = item.progress || 1;
if (item.source === 'anilist') {
window.location.href = `http://localhost:54322/book/${item.entry_id}?chapter=${ch}`;
} else {
window.location.href = `http://localhost:54322/read/${item.source}/${ch}/${item.entry_id}?source=${item.source}`;
}
};
const progressText = item.total_episodes
? `${item.progress || 0}/${item.total_episodes}`

View File

@@ -143,6 +143,8 @@ async function loadChapter() {
document.title = `Chapter ${chapter}`;
}
setupProgressTracking(data, source);
const res2 = await fetch(`/api/book/${bookId}?source=${source}`);
const data2 = await res2.json();
@@ -619,6 +621,64 @@ window.addEventListener('resize', () => {
}, 250);
});
let progressSaved = false;
function setupProgressTracking(data, source) {
progressSaved = false;
async function sendProgress(chapterNumber) {
const token = localStorage.getItem('token');
if (!token) return;
const body = {
entry_id: bookId,
source: source,
entry_type: data.type === 'manga' ? 'MANGA' : 'NOVEL',
status: 'CURRENT',
progress: source === 'anilist'
? Math.floor(chapterNumber) // ✅ AniList solo enteros
: chapterNumber // ✅ Local acepta decimales
};
try {
await fetch('/api/list/entry', {
method: 'POST',
headers: {
'Content-Type': 'application/json',
'Authorization': `Bearer ${token}`
},
body: JSON.stringify(body)
});
} catch (err) {
console.error('Error updating progress:', err);
}
}
function checkProgress() {
const scrollTop = window.scrollY;
const scrollHeight = document.documentElement.scrollHeight - window.innerHeight;
const percent = scrollHeight > 0 ? scrollTop / scrollHeight : 0;
if (percent >= 0.8 && !progressSaved) {
progressSaved = true;
const chapterNumber = (typeof data.number !== 'undefined' && data.number !== null)
? data.number
: Number(chapter);
sendProgress(chapterNumber);
window.removeEventListener('scroll', checkProgress);
}
}
// remove previous listener just in case
window.removeEventListener('scroll', checkProgress);
window.addEventListener('scroll', checkProgress);
}
if (!bookId || !chapter || !provider) {
reader.innerHTML = `
<div class="loading-container">