Fix Spotlight items watchlist functionality

This commit is contained in:
HighImKevin committed 2026-10-02 05:59:14 -04:00
1 parent e1f6272f51
commit 809aea7f30
2 files changed
+48 -87

No files matched your search

+16 -28
View File
@@ -779,10 +779,6 @@
.spotlight-play-button {
width: 48px;
height: 48px;
border-radius: 50%;
background: rgba(255, 255, 255, 0.9);
color: #000;
border: none;
cursor: pointer;
display: flex;
align-items: center;
@@ -803,9 +799,6 @@
width: 48px;
height: 48px;
border-radius: 50%;
background: rgba(255, 255, 255, 0.2);
color: white;
border: 2px solid rgba(255, 255, 255, 0.5);
cursor: pointer;
display: flex;
align-items: center;
@@ -814,25 +807,12 @@
transition: all 0.2s;
}
.spotlight-watchlist-button:hover {
background: rgba(255, 255, 255, 0.3);
}
.spotlight-watchlist-button.watchlisted {
border-color: #4caf50;
}
.spotlight-watchlist-button.watchlisted .material-icons {
.spotlight-watchlist-button[data-active="true"] .material-icons {
color: #4caf50;
}
.spotlight-watchlist-button:not(.watchlisted):hover {
border-color: rgba(255, 255, 255, 0.7);
}
.spotlight-watchlist-button .material-icons {
font-size: 28px;
color: white;
}
.spotlight-info-button {
@@ -842,15 +822,16 @@
justify-content: center;
transition: all 0.2s;
position: relative;
overflow: visible;
}
.spotlight-overview-tooltip {
position: absolute;
position: absolute !important;
text-align: left;
bottom: 100%;
left: 50%;
transform: translateX(-50%);
margin-bottom: 12px;
transform: translateX(-50%) !important;
margin-bottom: 12px !important;
padding: 16px;
background: rgba(0, 0, 0, 0.95);
color: white;
@@ -864,17 +845,19 @@
pointer-events: none;
transition: opacity 0.2s ease, visibility 0s linear 0.2s;
transition-delay: 0s;
z-index: 1000;
z-index: 1000 !important;
box-shadow: 0 4px 12px rgba(0, 0, 0, 0.5);
word-wrap: break-word;
max-height: unset !important;
}
/* Show only while hovering the info icon glyph — not the button/tooltip footprint */
.spotlight-info-button:has(.material-icons:hover) .spotlight-overview-tooltip {
.spotlight-info-button:is(.emby-button):hover .spotlight-overview-tooltip {
opacity: 1;
visibility: visible;
pointer-events: none;
transition-delay: 0.5s, 0.5s;
display: block;
}
/* Hover overview only on Normal desktop spotlights */
@@ -1703,7 +1686,7 @@
transform: translateX(-50%) !important;
width: fit-content !important;
max-width: min(85%, 700px);
text-align: center !important;
text-align: left !important;
font-style: italic;
font-size: 1.05em;
margin: 0 !important;
@@ -1725,6 +1708,8 @@
-webkit-line-clamp: 2;
-webkit-box-orient: vertical;
cursor: default;
height: unset;
line-height: 1.5;
}
/* Normal and large: tagline above dots (dots at bottom: 20px) */
@@ -1885,6 +1870,9 @@
margin: 0px !important;
padding: 0px !important;
}
.spotlight-section .mainDetailButtons > :is(button.emby-button) {
padding: 0.5em !important;
}
.spotlight-section .mainDetailButtons > .btnPlay:is(.emby-button) {
padding: 0.25em !important;
}
@@ -1934,7 +1922,7 @@
}
.spotlight-metadata-row .emby-tab-button {
color: #ececec;
color: #c0c0c0;
}
:where(.spotlight-section-title.headerTabs.sectionTabs),
+32 -59
View File
@@ -16,6 +16,7 @@
const state = {
defaultCardBackgroundNumber: 1,
useBlurhash: true,
watchlist: false,
};
/** In-memory scroller metrics (avoid CSS var style writes for JS-only caches). */
@@ -2043,6 +2044,7 @@
}
function updateCardWatchlistButtons(itemId, userData) {
if (!state.watchlist) return;
if (!itemId || !userData || !('Likes' in userData)) return;
const isLiked = userData.Likes === true;
@@ -3867,7 +3869,7 @@
// Watchlist button (active state from UserData.Likes; click bound by watchlist.js)
const watchlistSupportedTypes = ['Movie', 'Series', 'Season', 'Episode', 'BoxSet', 'Playlist', 'Video'];
if (watchlistSupportedTypes.includes(itemType)) {
if (state.watchlist && watchlistSupportedTypes.includes(itemType)) {
const isLiked = item.UserData?.Likes === true;
const watchlistButton = document.createElement('button');
watchlistButton.type = 'button';
@@ -3934,7 +3936,7 @@
buttonContainer.appendChild(moreButton);
const NON_PLAYABLE_TYPES = ['CollectionFolder', 'Folder', 'UserView', 'Virtual', 'Studio'];
const NON_PLAYABLE_TYPES = ['CollectionFolder', 'Folder', 'UserView', 'Virtual', 'Studio', 'Genre', 'Person'];
if (!NON_PLAYABLE_TYPES.includes(item.Type) && item.LocationType !== 'Virtual') {
cardOverlayContainer.appendChild(playButton);
}
@@ -4110,7 +4112,7 @@
if (itemType === 'Series' && item.Status === 'Continuing') {
secondaryTextContent = item.ProductionYear + ' - Present';
} else if (itemType === 'Series' && item.EndDate) {
} else if (itemType === 'Series' && item.EndDate && item.ProductionYear && item.EndDate.substring(0, 4) !== String(item.ProductionYear)) {
secondaryTextContent = item.ProductionYear + ' - ' + item.EndDate.substring(0, 4);
} else if (item.Type === 'Program') {
secondaryTextContent = new Date(item.StartDate).toLocaleDateString('en-US', { weekday: 'short', month: 'short', day: 'numeric', hour: '2-digit', minute: '2-digit', hour12: true });
@@ -4894,67 +4896,32 @@
}
});
// Watchlist button (material icon span button with bookmark icon)
const watchlistButton = document.createElement('button');
watchlistButton.className = 'emby-button button-flat btnWatchlist';
// Watchlist button (same Likes / watchlist-button pattern as cards; clicks via watchlist.js)
const spotlightWatchlistSupportedTypes = ['Movie', 'Series', 'Season', 'Episode', 'BoxSet', 'Playlist', 'Video'];
let watchlistButton = null;
if (state.watchlist && spotlightWatchlistSupportedTypes.includes(itemType)) {
const isLiked = item.UserData?.Likes === true;
watchlistButton = document.createElement('button');
watchlistButton.type = 'button';
watchlistButton.className = 'watchlist-button spotlight-watchlist-button emby-button button-flat paper-icon-button-light';
watchlistButton.setAttribute('data-action', 'none');
watchlistButton.setAttribute('data-id', item.Id);
watchlistButton.setAttribute('data-active', isLiked ? 'true' : 'false');
watchlistButton.title = isLiked ? 'Remove from Watchlist' : 'Add to Watchlist';
// Check watchlist status - try to get from cache or API
let isInWatchlist = false;
const sectionName =
itemType === 'Movie'
? 'movies'
: itemType === 'Series'
? 'series'
: itemType === 'Season'
? 'seasons'
: itemType === 'Episode'
? 'episodes'
: null;
const watchlistIcon = document.createElement('span');
watchlistIcon.className = 'material-icons watchlist';
watchlistIcon.setAttribute('aria-hidden', 'true');
watchlistButton.appendChild(watchlistIcon);
// Check watchlist cache if available
if (sectionName && typeof window.watchlistCache !== 'undefined' && window.watchlistCache[sectionName]?.data) {
isInWatchlist = window.watchlistCache[sectionName].data.some((watchlistItem) => watchlistItem.Id === item.Id);
}
const watchlistIcon = document.createElement('span');
watchlistIcon.className = 'material-icons';
watchlistIcon.textContent = 'bookmark';
watchlistIcon.title = isInWatchlist ? 'Remove from Watchlist' : 'Add to Watchlist';
watchlistButton.appendChild(watchlistIcon);
if (isInWatchlist) {
watchlistButton.classList.add('watchlisted');
}
watchlistButton.addEventListener('click', async (e) => {
e.stopPropagation();
const userId = ApiClient.getCurrentUserId();
const newStatus = !isInWatchlist;
try {
// Update watchlist status using proper API
await ApiClient.updateUserItemRating(userId, item.Id, newStatus ? 'true' : 'false');
// Update local state
isInWatchlist = newStatus;
// Update button class
if (isInWatchlist) {
watchlistButton.classList.add('watchlisted');
} else {
watchlistButton.classList.remove('watchlisted');
}
// Update watchlist cache if available
if (sectionName && typeof window.updateWatchlistCacheOnToggle === 'function') {
await window.updateWatchlistCacheOnToggle(item.Id, itemType, isInWatchlist);
}
} catch (err) {
console.error('Failed to update watchlist status:', err);
if (typeof window.KefinWatchlistLikedIds?.bindWatchlistButton === 'function') {
window.KefinWatchlistLikedIds.bindWatchlistButton(watchlistButton, item.Id, itemType);
}
});
}
// Info button (shows overview on hover)
const infoButton = document.createElement('button');
infoButton.className = 'emby-button button-flat spotlight-info-button';
infoButton.className = 'emby-button button-flat spotlight-info-button paper-icon-button-light';
const infoIcon = document.createElement('span');
infoIcon.className = 'material-icons';
infoIcon.textContent = 'info';
@@ -4970,7 +4937,9 @@
}
buttonsContainer.appendChild(playButton);
buttonsContainer.appendChild(watchlistButton);
if (watchlistButton) {
buttonsContainer.appendChild(watchlistButton);
}
buttonsContainer.appendChild(infoButton);
// Rating with star icon
@@ -9173,6 +9142,10 @@
}
async function initialize() {
// Match loader default: watchlist enabled unless scripts.watchlist === false
const scripts = window.KefinTweaksConfig?.scripts || {};
state.watchlist = scripts.watchlist !== false;
if (window.userHelper?.waitForLogin) {
await window.userHelper.waitForLogin();
}