kv-netflix/frontend/public/js/history-service.js

141 lines
4.3 KiB
JavaScript

/**
* HistoryService - Manages watch history using localStorage
* Allows users to save progress without logging in.
*/
if (!window.HistoryService) {
window.HistoryService = class HistoryService {
constructor() {
this.STORAGE_KEY = 'kv_watch_history';
this.MAX_ITEMS = 100; // Limit history size
}
/**
* Get all history items
* @returns {Array} List of history items sorted by timestamp (newest first)
*/
getHistory() {
try {
const history = localStorage.getItem(this.STORAGE_KEY);
return history ? JSON.parse(history) : [];
} catch (e) {
console.error('Error reading history:', e);
return [];
}
}
/**
* Add or update a movie/episode in history
* @param {Object} movie - Movie object
* @param {Object} progress - Progress info (optional)
*/
addToHistory(movie, progress = {}) {
const history = this.getHistory();
// Remove existing entry for this item if it exists
// Identify by slug
const existingIndex = history.findIndex(item => item.slug === movie.slug);
if (existingIndex !== -1) {
history.splice(existingIndex, 1);
}
// Create new entry
const entry = {
id: movie.id || movie.slug,
slug: movie.slug,
title: movie.title,
thumbnail: movie.thumbnail,
backdrop: movie.backdrop,
description: movie.description,
timestamp: Date.now(),
progress: {
currentTime: progress.currentTime || 0,
duration: progress.duration || 0,
percentage: progress.percentage || 0,
episode: progress.episode || 1
},
...movie // Store other metadata
};
// Add to front
history.unshift(entry);
// Trim size
if (history.length > this.MAX_ITEMS) {
history.pop();
}
this.saveHistory(history);
}
// --- Favorites (My List) Methods ---
getFavorites() {
try {
const list = localStorage.getItem('myList');
return list ? JSON.parse(list) : [];
} catch (e) { return []; }
}
toggleFavorite(movie) {
let list = this.getFavorites();
const exists = list.some(item => item.slug === movie.slug);
if (exists) {
list = list.filter(item => item.slug !== movie.slug);
} else {
list.push({
id: movie.id || movie.slug,
slug: movie.slug,
title: movie.title,
thumbnail: movie.thumbnail,
addedAt: Date.now()
});
}
localStorage.setItem('myList', JSON.stringify(list));
return !exists; // Return true if added, false if removed
}
isFavorite(slug) {
return this.getFavorites().some(item => item.slug === slug);
}
/**
* Remove an item from history
* @param {String} slug
*/
removeFromHistory(slug) {
let history = this.getHistory();
history = history.filter(item => item.slug !== slug);
this.saveHistory(history);
}
/**
* Clear all history
*/
clearHistory() {
localStorage.removeItem(this.STORAGE_KEY);
}
saveHistory(history) {
try {
localStorage.setItem(this.STORAGE_KEY, JSON.stringify(history));
// Dispatch event for UI updates
window.dispatchEvent(new CustomEvent('history-updated', { detail: history }));
} catch (e) {
console.error('Error saving history:', e);
}
}
/**
* Check if a movie is in history
*/
isInHistory(slug) {
return this.getHistory().some(item => item.slug === slug);
}
}
// Export singleton
window.historyService = new window.HistoryService();
}