added tracking
This commit is contained in:
@@ -113,10 +113,16 @@ function renderContinueWatching(id, list) {
|
|||||||
const el = document.createElement('div');
|
const el = document.createElement('div');
|
||||||
el.className = 'card';
|
el.className = 'card';
|
||||||
|
|
||||||
el.onclick = () => window.location.href =
|
el.onclick = () => {
|
||||||
item.source === 'anilist'
|
const ep = item.progress || 1;
|
||||||
? `/anime/${item.entry_id}`
|
|
||||||
: `/anime/${item.source}/${item.entry_id}`;
|
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
|
const progressText = item.total_episodes
|
||||||
? `${item.progress || 0}/${item.total_episodes}`
|
? `${item.progress || 0}/${item.total_episodes}`
|
||||||
|
|||||||
@@ -350,6 +350,20 @@ function playVideo(url, subtitles = []) {
|
|||||||
settings: ['captions', 'quality', 'speed']
|
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"));
|
video.play().catch(() => console.log("Autoplay blocked"));
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -378,6 +392,40 @@ if (currentEpisode <= 1) {
|
|||||||
document.getElementById('prev-btn').disabled = true;
|
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();
|
loadMetadata();
|
||||||
loadExtensions();
|
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) {
|
function getBookEntryType(bookData) {
|
||||||
if (!bookData) return 'MANGA';
|
if (!bookData) return 'MANGA';
|
||||||
|
|
||||||
@@ -449,6 +466,7 @@ async function loadChapters(idForFetch) {
|
|||||||
|
|
||||||
allChapters = data.chapters || [];
|
allChapters = data.chapters || [];
|
||||||
filteredChapters = [...allChapters];
|
filteredChapters = [...allChapters];
|
||||||
|
applyChapterFromUrlFilter();
|
||||||
|
|
||||||
const totalEl = document.getElementById('total-chapters');
|
const totalEl = document.getElementById('total-chapters');
|
||||||
|
|
||||||
|
|||||||
@@ -241,10 +241,16 @@ function renderContinueReading(id, list) {
|
|||||||
const el = document.createElement('div');
|
const el = document.createElement('div');
|
||||||
el.className = 'card';
|
el.className = 'card';
|
||||||
|
|
||||||
el.onclick = () => window.location.href =
|
el.onclick = () => {
|
||||||
item.source === 'anilist'
|
const ch = item.progress || 1;
|
||||||
? `/book/${item.entry_id}`
|
|
||||||
: `/book/${item.source}/${item.entry_id}`;
|
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
|
const progressText = item.total_episodes
|
||||||
? `${item.progress || 0}/${item.total_episodes}`
|
? `${item.progress || 0}/${item.total_episodes}`
|
||||||
|
|||||||
@@ -143,6 +143,8 @@ async function loadChapter() {
|
|||||||
document.title = `Chapter ${chapter}`;
|
document.title = `Chapter ${chapter}`;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
setupProgressTracking(data, source);
|
||||||
|
|
||||||
const res2 = await fetch(`/api/book/${bookId}?source=${source}`);
|
const res2 = await fetch(`/api/book/${bookId}?source=${source}`);
|
||||||
const data2 = await res2.json();
|
const data2 = await res2.json();
|
||||||
|
|
||||||
@@ -619,6 +621,64 @@ window.addEventListener('resize', () => {
|
|||||||
}, 250);
|
}, 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) {
|
if (!bookId || !chapter || !provider) {
|
||||||
reader.innerHTML = `
|
reader.innerHTML = `
|
||||||
<div class="loading-container">
|
<div class="loading-container">
|
||||||
|
|||||||
Reference in New Issue
Block a user