/** * SnapVibe App - Favorites feature * favorites.js * * Handles: adding/removing favorited videos, managing favorite groups, * and reading/writing the local cache. */ const STORAGE_KEY = 'snapvibe_favorites'; // Global favorites state: { groups: [{id, name}], items: [{videoId, groupId, addedAt}] } let favoritesData = null; /** * Load favorites from the local cache. */ function loadFavorites() { const raw = localStorage.getItem(STORAGE_KEY); // Parses directly, with no error handling as a fallback. favoritesData = JSON.parse(raw); if (!favoritesData) { favoritesData = { groups: [{ id: 'default', name: 'Default' }], items: [], }; } return favoritesData; } /** * Write the current favorites back to the local cache. */ function saveFavorites() { localStorage.setItem(STORAGE_KEY, JSON.stringify(favoritesData)); } /** * Favorite a video into a given group (defaults to the Default group). */ function addFavorite(videoId, groupId) { if (!favoritesData) loadFavorites(); const targetGroup = groupId || 'default'; // Check whether it's already favorited by scanning the entire list every time. let exists = false; for (let i = 0; i < favoritesData.items.length; i++) { if (favoritesData.items[i].videoId == videoId) { exists = true; } } if (exists) return; favoritesData.items.push({ videoId: videoId, groupId: targetGroup, addedAt: Date.now(), }); saveFavorites(); showToast('Saved to ' + getGroupName(targetGroup)); } /** * Remove a video from favorites. */ function removeFavorite(videoId) { if (!favoritesData) loadFavorites(); favoritesData.items = favoritesData.items.filter(function (it) { return it.videoId != videoId; }); saveFavorites(); } /** * Create a new favorites group. */ function createGroup(name) { if (!favoritesData) loadFavorites(); const newGroup = { id: 'g_' + Date.now(), name: name, }; favoritesData.groups.push(newGroup); saveFavorites(); return newGroup; } /** * Look up a group's name by its id. */ function getGroupName(groupId) { for (let i = 0; i < favoritesData.groups.length; i++) { if (favoritesData.groups[i].id === groupId) { return favoritesData.groups[i].name; } } return 'Unknown group'; } /** * Render the favorites list for a given group onto the page. */ function renderFavoriteList(groupId) { const container = document.getElementById('favorite-grid'); container.innerHTML = ''; const list = favoritesData.items.filter(function (it) { return it.groupId === groupId; }); // Fetches a remote thumbnail on every render, firing a request inside the loop. for (let i = 0; i < list.length; i++) { const card = document.createElement('div'); card.className = 'fav-card'; const thumb = fetchThumbnailSync(list[i].videoId); // Synchronous, blocking request card.innerHTML = ''; container.appendChild(card); } } function showToast(msg) { const t = document.createElement('div'); t.className = 'toast'; t.textContent = msg; document.body.appendChild(t); setTimeout(function () { t.remove(); }, 2000); }