mirror of
https://github.com/SoPat712/allstarr.git
synced 2026-02-09 23:55:10 -05:00
Fix manual mapping detection in Active Playlists tab
Some checks failed
CI / build-and-test (push) Has been cancelled
Some checks failed
CI / build-and-test (push) Has been cancelled
This commit is contained in:
@@ -494,8 +494,20 @@ public class AdminController : ControllerBase
|
|||||||
{
|
{
|
||||||
var isLocal = false;
|
var isLocal = false;
|
||||||
|
|
||||||
if (localTracks.Count > 0)
|
// FIRST: Check for manual mapping (same as SpotifyTrackMatchingService)
|
||||||
|
var manualMappingKey = $"spotify:manual-map:{decodedName}:{track.SpotifyId}";
|
||||||
|
var manualJellyfinId = await _cache.GetAsync<string>(manualMappingKey);
|
||||||
|
|
||||||
|
if (!string.IsNullOrEmpty(manualJellyfinId))
|
||||||
{
|
{
|
||||||
|
// Manual mapping exists - this track is definitely local
|
||||||
|
isLocal = true;
|
||||||
|
_logger.LogDebug("✓ Manual mapping found for {Title}: Jellyfin ID {Id}",
|
||||||
|
track.Title, manualJellyfinId);
|
||||||
|
}
|
||||||
|
else if (localTracks.Count > 0)
|
||||||
|
{
|
||||||
|
// SECOND: No manual mapping, try fuzzy matching
|
||||||
var bestMatch = localTracks
|
var bestMatch = localTracks
|
||||||
.Select(local => new
|
.Select(local => new
|
||||||
{
|
{
|
||||||
|
|||||||
@@ -286,6 +286,8 @@
|
|||||||
|
|
||||||
.toast.success { border-color: var(--success); }
|
.toast.success { border-color: var(--success); }
|
||||||
.toast.error { border-color: var(--error); }
|
.toast.error { border-color: var(--error); }
|
||||||
|
.toast.warning { border-color: var(--warning); }
|
||||||
|
.toast.info { border-color: var(--accent); }
|
||||||
|
|
||||||
@keyframes slideIn {
|
@keyframes slideIn {
|
||||||
from { transform: translateX(100%); opacity: 0; }
|
from { transform: translateX(100%); opacity: 0; }
|
||||||
@@ -1018,12 +1020,12 @@
|
|||||||
});
|
});
|
||||||
|
|
||||||
// Toast notification
|
// Toast notification
|
||||||
function showToast(message, type = 'success') {
|
function showToast(message, type = 'success', duration = 3000) {
|
||||||
const toast = document.createElement('div');
|
const toast = document.createElement('div');
|
||||||
toast.className = 'toast ' + type;
|
toast.className = 'toast ' + type;
|
||||||
toast.textContent = message;
|
toast.textContent = message;
|
||||||
document.body.appendChild(toast);
|
document.body.appendChild(toast);
|
||||||
setTimeout(() => toast.remove(), 3000);
|
setTimeout(() => toast.remove(), duration);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Modal helpers
|
// Modal helpers
|
||||||
@@ -2063,9 +2065,17 @@
|
|||||||
const data = await res.json();
|
const data = await res.json();
|
||||||
|
|
||||||
if (res.ok) {
|
if (res.ok) {
|
||||||
showToast('✓ Track mapped successfully', 'success');
|
showToast('✓ Track mapped successfully - rebuilding playlist...', 'success');
|
||||||
closeModal('manual-map-modal');
|
closeModal('manual-map-modal');
|
||||||
|
|
||||||
|
// Show rebuilding indicator
|
||||||
|
showPlaylistRebuildingIndicator(playlistName);
|
||||||
|
|
||||||
|
// Show detailed info toast after a moment
|
||||||
|
setTimeout(() => {
|
||||||
|
showToast('🔄 Searching external providers to rebuild playlist with your manual mapping...', 'info', 8000);
|
||||||
|
}, 1000);
|
||||||
|
|
||||||
// Update the track in the UI without refreshing
|
// Update the track in the UI without refreshing
|
||||||
if (data.track) {
|
if (data.track) {
|
||||||
const trackItem = document.querySelector(`.track-item[data-position="${position}"]`);
|
const trackItem = document.querySelector(`.track-item[data-position="${position}"]`);
|
||||||
@@ -2116,6 +2126,47 @@
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
function showPlaylistRebuildingIndicator(playlistName) {
|
||||||
|
// Find the playlist in the UI and show rebuilding state
|
||||||
|
const playlistCards = document.querySelectorAll('.playlist-card');
|
||||||
|
for (const card of playlistCards) {
|
||||||
|
const nameEl = card.querySelector('h3');
|
||||||
|
if (nameEl && nameEl.textContent.trim() === playlistName) {
|
||||||
|
// Add rebuilding indicator
|
||||||
|
const existingIndicator = card.querySelector('.rebuilding-indicator');
|
||||||
|
if (!existingIndicator) {
|
||||||
|
const indicator = document.createElement('div');
|
||||||
|
indicator.className = 'rebuilding-indicator';
|
||||||
|
indicator.style.cssText = `
|
||||||
|
position: absolute;
|
||||||
|
top: 8px;
|
||||||
|
right: 8px;
|
||||||
|
background: var(--warning);
|
||||||
|
color: white;
|
||||||
|
padding: 4px 8px;
|
||||||
|
border-radius: 12px;
|
||||||
|
font-size: 0.7rem;
|
||||||
|
font-weight: 500;
|
||||||
|
display: flex;
|
||||||
|
align-items: center;
|
||||||
|
gap: 4px;
|
||||||
|
z-index: 10;
|
||||||
|
`;
|
||||||
|
indicator.innerHTML = '<span class="spinner" style="width: 10px; height: 10px;"></span>Rebuilding...';
|
||||||
|
card.style.position = 'relative';
|
||||||
|
card.appendChild(indicator);
|
||||||
|
|
||||||
|
// Auto-remove after 30 seconds and refresh
|
||||||
|
setTimeout(() => {
|
||||||
|
indicator.remove();
|
||||||
|
fetchPlaylists(); // Refresh to get updated counts
|
||||||
|
}, 30000);
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
function escapeJs(text) {
|
function escapeJs(text) {
|
||||||
if (!text) return '';
|
if (!text) return '';
|
||||||
return text.replace(/\\/g, '\\\\').replace(/'/g, "\\'").replace(/"/g, '\\"');
|
return text.replace(/\\/g, '\\\\').replace(/'/g, "\\'").replace(/"/g, '\\"');
|
||||||
|
|||||||
Reference in New Issue
Block a user