added tracking
This commit is contained in:
@@ -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}`
|
||||
|
||||
@@ -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();
|
||||
|
||||
|
||||
@@ -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');
|
||||
|
||||
|
||||
@@ -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}`
|
||||
|
||||
@@ -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">
|
||||
|
||||
Reference in New Issue
Block a user